kubernetes 学习 尚硅谷
出自 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 名为 namekubectl 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}:删除servicekubectl get ingress/ing :获取集群中的 ingerss
kubectl edit ing {ing name}:修改 ingress 配置kubectl get pv:获取所有 pv
kubectl get pvc:获取所有 pvckubectl 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-utilsyum 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# 启动 dockersystemctl start docker# 查看 docker 是否成功, 有 Client 和 Server 即成功docker version# 配置加速镜像sudo mkdir -p /etc/dockersudo 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"}EOFsudo systemctl daemon-reloadsudo systemctl restart docker# 查看是否配置成功docker info# 查看主机名hostname# 设置主机名 每台服务器主机名不可重复hostnamectl set-hostname k8s-masterhostnamectl set-hostname k8s-node-1hostnamectl set-hostname k8s-node-2# 命令行显示设置的主机名bash# 查看 交换分区free -m# 将 SELinux 设置为 permissive 模式(相当于将其禁用) 第一行是临时禁用,第二行是永久禁用setenforce 0sed -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.confbr_netfilterEOFcat <<EOF | sudo tee /etc/sysctl.d/k8s.confnet.bridge.bridge-nf-call-ip6tables = 1net.bridge.bridge-nf-call-iptables = 1EOF# 让配置生效sysctl --system
安装 kubelet、kubeadm、kubectl
# 配置 k8s 的 yum 源地址cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo[kubernetes]name=Kubernetesbaseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64enabled=1gpgcheck=0repo_gpgcheck=0gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpghttp://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpgEOF# 安装 kubelet、kubeadm、kubectlyum install -y kubelet-1.20.9 kubeadm-1.20.9 kubectl-1.20.9 --disableexcludes=kubernetes# 启动kubeletsystemctl enable --now kubelet# 查看 kubelet 状态:一会停止 一会运行。 这个状态是对的,kubelet 等待 kubeadm 发号指令。systemctl status kubelet
下载镜像
# 配置镜像,生成 images.shsudo tee ./images.sh <<-'EOF'#!/bin/bashimages=(kube-apiserver:v1.20.9kube-proxy:v1.20.9kube-controller-manager:v1.20.9kube-scheduler:v1.20.9coredns:1.7.0etcd:3.4.13-0pause:3.2)for imageName in ${images[@]} ; dodocker pull registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/$imageNamedoneEOF# 拉取镜像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/.kubesudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/configsudo chown $(id -u):$(id -g) $HOME/.kube/configAlternatively, if you are the root user, you can run:export KUBECONFIG=/etc/kubernetes/admin.confYou 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 authoritiesand 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/.kubesudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/configsudo chown $(id -u):$(id -g) $HOME/.kube/config#部署网络插件 在master执行# 下载 calico.yamlcurl https://docs.projectcalico.org/manifests/calico.yaml -Ocurl 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 改成 NodePortkubectl 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-usernamespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:name: admin-user
roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: cluster-admin
subjects:
- kind: ServiceAccountname: admin-usernamespace: 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: myngnixports:-containerPort: 80 # 设置端口- image: tomcat:8.5.68name: mytomcat
部署多副本pod
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: my-depname: my-dep
spec:replicas: 3 # 多副本selector:matchLabels:app: my-deptemplate:metadata:labels:app: my-depspec:containers:- image: nginxname: mynginx
service
pod 的服务发现和负载均衡
创建 service,service 通过 pod 的标签进行对应的服务器转发
apiVersion: v1
kind: Service # 关键字
metadata:labels:k8s-app: my-dep-02name: my-dep-02
spec:selector:k8s-app: my-dep-02 # 标签名ports:- port: 8000protocal: TCPtargetPort: 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: nginxrules:- host: "my"http:paths:- pathType: Prefixpath: "/"backend:service:name: mynginxport:number: 8000 # hello-server (service) 的端口是 8000- host: "you"http:paths:- pathType: Prefixpath: "/" # 把请求会转给下面的服务,下面的服务一定要能处理这个路径,不能处理就是404backend:service:name: younginx #java,比如使用路径重写,去掉前缀nginxport: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/exportsmkdir -p /nfs/datasystemctl enable rpcbind --nowsystemctl enable nfs-server --now# 配置生效exportfs -r# 查看exportfs# 检查,下面的 IP 是master IPshowmount -e 192.168.27.251# 在 2 个从服务器 执行,执行以下命令挂载 nfs 服务器上的共享目录到本机路径 /root/nfsmountmkdir -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/datals# 在 从服务器 修改,然后去 其他 服务器 查看,也能 同步
原生方式数据挂载
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: nginx-pv-demoname: nginx-pv-demo
spec:replicas: 2selector:matchLabels:app: nginx-pv-demotemplate:metadata:labels:app: nginx-pv-demospec:containers:- image: nginxname: nginxvolumeMounts:- name: htmlmountPath: /usr/share/nginx/html # 挂载目录volumes:# 和 volumeMounts.name 一样- name: htmlnfs:# master IP 实际文件存储地址server: 192.168.27.251path: /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:- ReadWriteManystorageClassName: nfsnfs:# 挂载 上面创建过的文件夹path: /nfs/data/01# nfs 主节点服务器的 IPserver: 192.168.27.251
---
apiVersion: v1
kind: PersistentVolume
metadata:# 这个name 要小写,如 Gi 大写就不行name: pv02-1gi
spec:capacity:storage: 1GiaccessModes:- ReadWriteManystorageClassName: nfsnfs:path: /nfs/data/02# nfs 主节点服务器的 IPserver: 192.168.27.251
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv03-3gi
spec:capacity:storage: 3GiaccessModes:- ReadWriteManystorageClassName: nfsnfs:path: /nfs/data/03# nfs 主节点服务器的 IPserver: 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:- ReadWriteManyresources:requests:# 需要 200M的 PVstorage: 200Mi# 上面 PV 写的什么 这里就写什么 storageClassName: nfs
使用
vi pvc.yaml# 复制上面配置kubectl get pvkubectl apply -f pvc.yamlkubectl get pvkubectl get pvc
创建pod 绑定 pvc
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: nginx-deploy-pvcname: nginx-deploy-pvc
spec:replicas: 2selector:matchLabels:app: nginx-deploy-pvctemplate:metadata:labels:app: nginx-deploy-pvcspec:containers:- image: nginxname: nginxvolumeMounts:- name: htmlmountPath: /usr/share/nginx/htmlvolumes:- name: html# 之前是 nfs,这里用 pvcpersistentVolumeClaim:claimName: nginx-pvc
使用
vi dep02.yaml# 复制上面 yamlkubectl apply -f dep02.yamlkubectl get podkubectl get pvkubectl get pvc
ConfigMap
挂载配置文件
vi redis.conf
# 写
appendonly yes# 创建配置,redis保存到k8s的etcd;
kubectl create cm redis-conf --from-file=redis.conf# 查看
kubectl get cmrm -rf redis.confkubectl get cm redis.conf -oyaml 获取配置文件的yaml文件信息
使用configmap 的配置启动pod
apiVersion: v1
kind: Pod
metadata:name: redis
spec:containers:- name: redisimage: rediscommand:# 启动命令- redis-server# 指的是redis容器内部的位置- "/redis-master/redis.conf" ports:- containerPort: 6379volumeMounts: #目录挂载- mountPath: /dataname: data- mountPath: /redis-mastername: configvolumes:- name: dataemptyDir: {}- name: configconfigMap: # 读取configmap的文件信息name: redis-confitems:- key: redis.confpath: 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-dockerimage: cgxin/cgxin_docker:1.0# 加上 Secret imagePullSecrets:- name: cgxin-docker-secret