出自 https://www.bilibili.com/video/BV13Q4y1C7hS
相关命令
kubeadm init :将当前节点创建为主节点
kubectl get nodes:获取集群所有节点
kubectl apply -f xxx.yaml:根据配置文件,给集群创建资源
kubectl delete -f xx.yaml:删除配置文件创建的资源
kubectl get pod -A:查看集群部署了那些应用,只能在主节点执行,不加 -A 获取默认 defalut 命名空间下的pod, -n namespace 查看对应 namespace下的pod。--show-labels 查看pod 标签
kubectl get pod -A -w :检测 pod 变化,每次变化就输出信息, -owide 显示pod详细信息,每个pod 集群都会分配一个ip
kubeadm token create --print-join-command: 重新获取令牌
kubectl describe pod {name}:查看对应 pod 的描述信息,-n 指定命名空间,主要查看 events 中的信息
kubectl get ns :获取集群下所有命名空间
kubectl delete ns {namespace} :删除指定命名空间
kubectl create ns {namespace} :创建命名空间,还可以使用 yaml 文件创建命令空间,具体见后面
kubectl logs -f -n {namespace} 容器名:查看指定容器日志
kubectl run {name} --image={nginx}: 创建 nginx 的pod,pod 名为 name
kubectl exec -it {pod name} -- /bin/bash:进入 pod 内部
kubectl create deployment {name} --image={image name}:创建一次应用部署,使用这个部署,删除对应pod时会新建一个部署pod。--replicas=3 部署三个pod
kubectl get deploy:获取所有部署。-oyaml 查看部署的yaml文件
kubectl delete deploy {deploy name}: 删除部署,才能真正删除,不然只会新创建pod
kubectl edit deploy {deploy name}:可修改 deploy 内容
kubectl scale deploy/{deploy name} --replicas=5:扩缩容,扩容成5个pod,replicas控制pod数
kubectl set image deployment/{deploy name} {image name}=nginx:1.16.1 --record :滚动更新,相当于将当前 pod 升级成 nginx:1.16.1 镜像,--record 在 rollout histroy 记录
kubectl set image deployment-name container-name=image-name 语法错了
kubectl rollout history deploment/{deploy name}:版本回退,查看版本信息
kubectl rollout history deploment/{deploy name} --revision=2:版本回退。--revision 是上面的版本信息 revision 值
kubectl expose deploy {deploy name} --port=8000 --target-port=80 --type=ClusterIP:向外暴露8000 端口,映射向所有 deploy 相关pod 的 80 端口。ClusterIP 生成集群ip,NodePort 既有集群ip,也可公网访问,会在每台机器开发一个公网端口
kubectl get service|svc:可获取 上面这个命令的集群 ip 地址,可用通过该 ip 地址加端口访问到 pod。也有域名生成,详情看 service 内容。
kubectl delete service {service name} -n {namespace}:删除service
kubectl get ingress/ing :获取集群中的 ingerss
kubectl edit ing {ing name}:修改 ingress 配置
kubectl get pv:获取所有 pv
kubectl get pvc:获取所有 pvc
kubectl get cm:获取 etcd 的配置文件信息
kubectl get cm {cm name} -oyaml:获取指定的配置文件内容
特性
服务发现和负载均衡
存储编排
自动部署和回滚
自动完成装箱计算
自我修复
架构
Kubernetes Cluster = N Master Node + N Worker Node: N 主节点 + N 工作节点; N >= 1
主从集群。
组件介绍
kube-apiserver
Kubernetes 控制面的组件,该组件公开了 Kubernetes API。API服务器是 Kubernetes 控制面的前端。 Kubernetes API 服务器的主要实现是 kube-apiserver。kube-apiserver 设计上考虑了水平伸缩,也就是说,它可通过部署多个实例来进行扩缩。你可以运行 kube-apiserver 的多个实例,并在这些实例之间平衡流量。
etcd
兼具一致性和高可用性的键值数据库,可以作为保存 Kubernetes 所有集群数据的后台数据库。
kube-scheduler
控制平面组件,负责监视新创建的、未指定运行节点 (node) 的 Pods,选择节点让 Pod 在上面运行。
调度决策考虑的因素包括单个 Pod 和 Pod 集合的资源需求、硬件/软件/策略约束、亲和性和反亲和性规范、数据位置、工作负载间的工作干扰和最后时限。
kube-controller-manager
在主节点上运行 控制器 的组件。
在逻辑上讲,每个控制器都是一个单独的进程,但是为了降低复杂性,它们都被编译到同一个可执行文件,并在一个进程中运行。
这些控制器包括:
- 节点控制器(Node Controller):负责在节点出现故障时进行通知和响应。
- 任务控制器(Job Controller):检测代表一次性任务的 Job 对象,然后创建 Pods 来运行这些任务直至完成。
- 端点控制器(Endpoints Controller):填充端点 (Endpoints) 对象(即加入Service 与 Pod)。
- 服务账户和令牌控制器(Service Account & Token Controllers):为新的命名空间创建默认账户和 API 控制令牌。
cloud-controller-manager
云控制器管理器是指嵌入特定云的逻辑控制的控制平面组件。云控制器管理器允许链接集群到云提供商的应用编程接口中,并把和该云平台交互的组件只和你的集群交互的组件分离开
节点组件
kubelet
kubelet 会在集群中每个节点 (node) 上运行。它保证容器 (containers) 都运行在 Pod 中。
kubelet 接收一组通过各类机制提供给他的 PodSpec,确保这些 PodSpec 中描述的容器处于运行状态且健康。kubelet 不会管理不是有 Bubernetes 创建的容器。
kube-proxy
kube-proxy 是集群中每个节点上运行的网络代理,实现 Kubernetes 服务 (Service) 概念的一部分。
如果操作系统提供了数据包过滤层并可用的话,kube-proxy 会通过它来实现网络规则。负责,kube-proxy 仅转发流量本身。
集群搭建
先安装 docker 、 kubelet、kubectl(命令行软件,只装master节点即可) 、kubeadm(集群管理软件)
安装步骤:
安装docker
# 安装/更新 yum-utils
yum install -y yum-utils
# 配置 yum源
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 安装 docker 20.10.7 版本
yum -y install docker-ce-20.10.7 docker-ce-cli-20.10.7 containerd.io-1.4.6
# 查看 docker 版本
docker -v
# 启动 docker
systemctl start docker
# 查看 docker 是否成功, 有 Client 和 Server 即成功
docker version
# 配置加速镜像
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://nbbnw70c.mirror.aliyuncs.com"],
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
# 查看是否配置成功
docker info
# 查看主机名
hostname
# 设置主机名 每台服务器主机名不可重复
hostnamectl set-hostname k8s-master
hostnamectl set-hostname k8s-node-1
hostnamectl set-hostname k8s-node-2
# 命令行显示设置的主机名
bash
# 查看 交换分区
free -m
# 将 SELinux 设置为 permissive 模式(相当于将其禁用) 第一行是临时禁用,第二行是永久禁用
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
# 关闭swap;第一行是临时禁用,第二行是永久禁用
swapoff -a
sed -ri 's/.*swap.*/#&/' /etc/fstab
# 允许 iptables 检查桥接流量 (K8s 官方要求)
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
# 让配置生效
sysctl --system
安装 kubelet、kubeadm、kubectl
# 配置 k8s 的 yum 源地址
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
# 安装 kubelet、kubeadm、kubectl
yum install -y kubelet-1.20.9 kubeadm-1.20.9 kubectl-1.20.9 --disableexcludes=kubernetes
# 启动kubelet
systemctl enable --now kubelet
# 查看 kubelet 状态:一会停止 一会运行。 这个状态是对的,kubelet 等待 kubeadm 发号指令。
systemctl status kubelet
下载镜像
# 配置镜像,生成 images.sh
sudo tee ./images.sh <<-'EOF'
#!/bin/bash
images=(
kube-apiserver:v1.20.9
kube-proxy:v1.20.9
kube-controller-manager:v1.20.9
kube-scheduler:v1.20.9
coredns:1.7.0
etcd:3.4.13-0
pause:3.2
)
for imageName in ${images[@]} ; do
docker pull registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/$imageName
done
EOF
# 拉取镜像
chmod +x ./images.sh && ./images.sh
# 所有机器添加 master 域名映射,以下 IP 为 master 的 IP;
# 访问 cluster-endpoint 即 访问 192.168.58.128 确立主节点,就是绑定域名和ip,确保访问这个域名是进主节点
echo "192.168.58.128 cluster-endpoint" >> /etc/hosts
# 主节点初始化 (只在 master 服务器执行, 其他 node 不用)
# --apiserver-advertise-address: master 的 IP
# --control-plane-endpoint: master 的域名
# --service-cidr 和 --pod-network-cidr 是网络范围,雷神 建议不要改。要改的话 2 个cidr 和 vps(172.31.x.x 虚拟机ip) 的,3 个网络互相不能重叠;还要修改 calico.yaml的 IP(下图有写)。
kubeadm init \
--apiserver-advertise-address=192.168.58.128 \
--control-plane-endpoint=cluster-endpoint \
--image-repository registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images \
--kubernetes-version v1.20.9 \
--service-cidr=10.96.0.0/16 \
--pod-network-cidr=192.168.0.0/16 --pod-network-cidr=10.244.0.0/16
# 等待出现
Your Kubernetes control-plane has initialized successfully! 即代表主节点k8s安装成功
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user: 要使用集群先执行以下命令
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Alternatively, if you are the root user, you can run:
export KUBECONFIG=/etc/kubernetes/admin.conf
You should now deploy a pod network to the cluster. 部署网络插件执行下方命令
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
You can now join any number of control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following as root: 想往集群加入主节点执行下方命令
kubeadm join cluster-endpoint:6443 --token sax5xc.t5ofavb0mp6g062r \
--discovery-token-ca-cert-hash sha256:791b326a5dae521ec40add360da9740df4ccdf291f30a88b68c1e422d20b391b \
--control-plane
Then you can join any number of worker nodes by running the following on each as root: 往集群增加工作节点执行下方命令
kubeadm join cluster-endpoint:6443 --token sax5xc.t5ofavb0mp6g062r \
--discovery-token-ca-cert-hash sha256:791b326a5dae521ec40add360da9740df4ccdf291f30a88b68c1e422d20b391b
#先执行
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
#部署网络插件 在master执行
# 下载 calico.yaml
curl https://docs.projectcalico.org/manifests/calico.yaml -O
curl https://docs.projectcalico.org/v3.8/manifests/calico.yaml -O
curl https://docs.projectcalico.org/v3.20/manifests/calico.yaml -O 可用的
# 加载配置
kubectl apply -f calico.yaml
加载配置时,配置中有 192.168.0.0 的ip地址需对应之前设置主节点的 pod-network-cidr 值,故此处需改成 10.244.0.0
#查看节点状态
kubectl get pods -A 等所有 pod 都 running后,执行
kubectl get nodes 可以查看到 主节点页 ready 了
# 将从节点加入集群
kubeadm join cluster-endpoint:6443 --token sax5xc.t5ofavb0mp6g062r \
--discovery-token-ca-cert-hash sha256:791b326a5dae521ec40add360da9740df4ccdf291f30a88b68c1e422d20b391b
此命令是执行主节点初始化时日志输出的。
看到 The node has joined the cluster 即代表当前节点已加入集群
然后在主节点执行 kubectl get nodes 可查看到具体节点信息
需等待pod 都 running 后才可进行具体操作
安装完成后在任一节点执行命令 kubeadm init 手动指定主节点,主节点安装 scheduler、kube-proxy、api-server、etcd、controller-manager等。然后在其他节点执行 kubeadm join 加入集群。从节点安装 kube-proxy。
安装可视化界面
在 master 执行
```bash
# 根据 在线配置文件 创建资源,也可以将文件下载下来直接用,这是获取在线配置文件
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.3.1/aio/deploy/recommended.yaml
https://github.com/kubernetes/dashboard/blob/v2.3.1/aio/deploy/recommended.yaml
设置访问端口
# 修改配置文件 找到 type,将 ClusterIP 改成 NodePort
kubectl edit svc kubernetes-dashboard -n kubernetes-dashboard
# 找到端口,在安全组放行
kubectl get svc -A |grep kubernetes-dashboard 输出内容会包含端口
```
创建dashboard 访问token
在 master 执行
# 创建 dash-usr.yaml,加入下面配置
vi dash-usr.yaml
# 创建访问账号,准备一个yaml文件,加入下面配置
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin-user
namespace: kubernetes-dashboard
# 在 k8s 集群中创建资源
kubectl apply -f dash-usr.yaml
# 获取访问令牌
kubectl -n kubernetes-dashboard get secret $(kubectl -n kubernetes-dashboard get sa/admin-user -o jsonpath="{.secrets[0].name}") -o go-template="{{.data.token | base64decode}}"
操作 kubectl
使用 yaml 创建 hello 命名空间
创建pod
创建 nginx 的pod,直接 kubectl apply -f 即可
apiVersion: v1
kind: Pod
metadata:
labels:
run: mynginx-yaml
# Pod 的 名字
name: mynginx-yaml
# 指定命名空间 (不写是 默认 default)
namespace: default
spec:
containers:
# 多个 容器,多个 -
- image: nginx
# 容器的名字
name: mgninx-yaml
创建 nginx 和 tomcat 的pod
apiVersion: v1
kind: Pod
metadata:
labels:
run: myapp
# Pod 的 名字
name: myapp
# 指定命名空间 (不写是 默认 default)
namespace: default
spec:
replicas: 3 # 副本数
containers:
# 多个 容器,多个 -
- image: nginx
# 容器的名字
name: myngnix
ports:
-containerPort: 80 # 设置端口
- image: tomcat:8.5.68
name: mytomcat
部署多副本pod
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: my-dep
name: my-dep
spec:
replicas: 3 # 多副本
selector:
matchLabels:
app: my-dep
template:
metadata:
labels:
app: my-dep
spec:
containers:
- image: nginx
name: mynginx
service
pod 的服务发现和负载均衡
创建 service,service 通过 pod 的标签进行对应的服务器转发
apiVersion: v1
kind: Service # 关键字
metadata:
labels:
k8s-app: my-dep-02
name: my-dep-02
spec:
selector:
k8s-app: my-dep-02 # 标签名
ports:
- port: 8000
protocal: TCP
targetPort: 80
service 域名访问规则:服务名.所在命名空间.svc,集群内可用
Ingress
service 的统一网关入口,底层就是 nginx
官网地址 https://kubernetes.github.io/ingress-nginx/
#安装
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.47.0/deploy/static/provider/baremetal/deploy.yaml
https://github.com/kubernetes/ingress-nginx/blob/controller-v0.47.0/deploy/static/provider/baremetal/deploy.yaml
# 修改镜像
vi deploy.yaml
# 将 image 的值改为如下值
registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/ingress-nginx-controller:v0.46.0
# 安装资源
kubectl apply -f deploy.yaml
# 检查安装的结果
kubectl get pod,svc -n ingress-nginx
# 最后别忘记把 svc 暴露的端口 在安全组放行
安装完成后,会有一个 http端口和https 端口可拱外网使用。
配置 ingress 域名转发规则
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-host-bar
spec:
ingressClassName: nginx
rules:
- host: "my"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: mynginx
port:
number: 8000 # hello-server (service) 的端口是 8000
- host: "you"
http:
paths:
- pathType: Prefix
path: "/" # 把请求会转给下面的服务,下面的服务一定要能处理这个路径,不能处理就是404
backend:
service:
name: younginx #java,比如使用路径重写,去掉前缀nginx
port:
number: 8001
kubectl apply -f ingerss-test.yaml 应用该规则,访问 ingress 端口,会进行服务转发
存储抽象
类似 docker 的挂载。
NFS 搭建
#所有机器执行
yum install -y nfs-utils
# 只在 mster 机器执行:nfs主节点,rw 读写
echo "/nfs/data/ *(insecure,rw,sync,no_root_squash)" > /etc/exports
mkdir -p /nfs/data
systemctl enable rpcbind --now
systemctl enable nfs-server --now
# 配置生效
exportfs -r
# 查看
exportfs
# 检查,下面的 IP 是master IP
showmount -e 192.168.27.251
# 在 2 个从服务器 执行,执行以下命令挂载 nfs 服务器上的共享目录到本机路径 /root/nfsmount
mkdir -p /nfs/data
# 在 2 个从服务器执行,将远程 和本地的 文件夹 挂载
mount -t nfs 192.168.27.251:/nfs/data /nfs/data
# 在 master 服务器,写入一个测试文件
echo "hello nfs server" > /nfs/data/test.txt
# 在 2 个从服务器查看
cd /nfs/data
ls
# 在 从服务器 修改,然后去 其他 服务器 查看,也能 同步
原生方式数据挂载
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-pv-demo
name: nginx-pv-demo
spec:
replicas: 2
selector:
matchLabels:
app: nginx-pv-demo
template:
metadata:
labels:
app: nginx-pv-demo
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html # 挂载目录
volumes:
# 和 volumeMounts.name 一样
- name: html
nfs:
# master IP 实际文件存储地址
server: 192.168.27.251
path: /nfs/data/nginx-pv # 要提前创建好文件夹,否则挂载失败
PV 和 PVC
PV:持久卷(Persistent Volume),将应用需要持久化的数据保存到指定位置
PVC:持久卷申明(Persistent Volume Claim),申明需要使用的持久卷规格
挂载目录。ConfigMap 挂载配置文件。
这里是 是 静态的, 就是自己创建好了 容量,然后 PVC 去挑。 还有 动态供应的,不用手动去创建 PV池子。
创建3个 PV
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv01-10m
spec:
# 限制容量
capacity:
storage: 10M
# 读写模式:可读可写
accessModes:
- ReadWriteMany
storageClassName: nfs
nfs:
# 挂载 上面创建过的文件夹
path: /nfs/data/01
# nfs 主节点服务器的 IP
server: 192.168.27.251
---
apiVersion: v1
kind: PersistentVolume
metadata:
# 这个name 要小写,如 Gi 大写就不行
name: pv02-1gi
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
storageClassName: nfs
nfs:
path: /nfs/data/02
# nfs 主节点服务器的 IP
server: 192.168.27.251
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv03-3gi
spec:
capacity:
storage: 3Gi
accessModes:
- ReadWriteMany
storageClassName: nfs
nfs:
path: /nfs/data/03
# nfs 主节点服务器的 IP
server: 192.168.27.251
执行 PV 创建
vi pv.yaml
# 复制上面文件
kubectl apply -f pv.yaml
# 查看 pv, kubectl get pv
kubectl get persistentvolume
创建 PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nginx-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
# 需要 200M的 PV
storage: 200Mi
# 上面 PV 写的什么 这里就写什么
storageClassName: nfs
使用
vi pvc.yaml
# 复制上面配置
kubectl get pv
kubectl apply -f pvc.yaml
kubectl get pv
kubectl get pvc
创建pod 绑定 pvc
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-deploy-pvc
name: nginx-deploy-pvc
spec:
replicas: 2
selector:
matchLabels:
app: nginx-deploy-pvc
template:
metadata:
labels:
app: nginx-deploy-pvc
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
# 之前是 nfs,这里用 pvc
persistentVolumeClaim:
claimName: nginx-pvc
使用
vi dep02.yaml
# 复制上面 yaml
kubectl apply -f dep02.yaml
kubectl get pod
kubectl get pv
kubectl get pvc
ConfigMap
挂载配置文件
vi redis.conf
# 写
appendonly yes
# 创建配置,redis保存到k8s的etcd;
kubectl create cm redis-conf --from-file=redis.conf
# 查看
kubectl get cm
rm -rf redis.conf
kubectl get cm redis.conf -oyaml 获取配置文件的yaml文件信息
使用configmap 的配置启动pod
apiVersion: v1
kind: Pod
metadata:
name: redis
spec:
containers:
- name: redis
image: redis
command:
# 启动命令
- redis-server
# 指的是redis容器内部的位置
- "/redis-master/redis.conf"
ports:
- containerPort: 6379
volumeMounts: #目录挂载
- mountPath: /data
name: data
- mountPath: /redis-master
name: config
volumes:
- name: data
emptyDir: {}
- name: config
configMap: # 读取configmap的文件信息
name: redis-conf
items:
- key: redis.conf
path: redis.conf
secret
验证用户使用
kubectl create secret docker-registry cgxin-docker-secret \
--docker-username=leifengyang \
--docker-password=Lfy123456 \
--docker-email=534096094@qq.com
cgxin-docker-secret 是自定义名称
##命令格式
kubectl create secret docker-registry regcred \
--docker-server=<你的镜像仓库服务器> \
--docker-username=<你的用户名> \
--docker-password=<你的密码> \
--docker-email=<你的邮箱地址>
kubectl get secret {docker name} -oyaml
拉取私有镜像,带上 secret
apiVersion: v1
kind: Pod
metadata:
name: private-cgxin-docker
spec:
containers:
- name: private-cgxin-docker
image: cgxin/cgxin_docker:1.0
# 加上 Secret
imagePullSecrets:
- name: cgxin-docker-secret