# [kubernetes]kubernetes學習筆記 (一) ###### tags `kubernetes` ---- #### 1.搭建kubernetes集群 ##### Kubernetes 组件介绍 - 一个 kubernetes 集群主要由控制节点(master)、工作节点(node)构成,每个节点上都会安装不同的组件。 - 控制节点(master):集群的控制平面,负责集群的决策。 - API Server:集群操作的唯一入口,接收用户输入的命令,提供认证、授权、API注册和发现等机制,同时协调各组件的工作。 - Scheduler:负责集群资源调度,按照预定的调度策略将 Pod 调度到相应的 node 节点上。 - ControllerManager:负责维护集群的状态,比如程序部署安排、故障检测、自动扩展和滚动更新等。 - Etcd:负责存储集群中各种资源对象的信息。 - 工作节点(node):集群的数据平面,负责为容器提供运行环境。 - Kubelet:负责维护容器的生命周期,即通过控制 Docker ,来创建、更新、销毁容器。 - KubeProxy:负责提供集群内部的服务发现和负载均衡。 - Docker:负责节点上容器的各种操作。 - 部署网络组件的作用? 实现容器跨主机网络通信 - 容器接口 CNI 容器网络接口 CRI 容器运行时接口 (对接容器接口) CSI 容器存储接口 - k8s弃用docker前,与弃用后 k8s -> docker-shim/cri -> docker (有dockershim,默认能兼容docker) k8s -> cri -> docker(支持cri) (后期需要docker去兼容对接 CRI) ##### 1.1.环境准备 ```shell master 192.168.3.124 node1 192.168.3.125 node2 192.168.3.126 ##### 关闭防火墙 systemctl stop firewalld systemctl disable firewalld #关闭selinux sed -i 's/enforcing/disabled/' /etc/selinux/config # 永久 setenforce 0 # 临时 #关闭swap swapoff -a # 临时 sed -ri 's/.*swap.*/#&/' /etc/fstab # 永久,sed中&,经常用来在原文本下增加字符串,其中&就相当于要被替换".*swap.* swapoff -a && swapon -a #刷新swp (在初始化得时候如果常出现swp报错请重启服务器,然后再执行一遍关闭swp得命令) #修改主机名,修改hosts vim /etc/hosts 192.168.3.124 master 192.168.3.125 node01 192.168.3.126 node02 #将桥接ipv4流量传递到iptables的链上 cat > /etc/sysctl.d/k8s.conf << EOF net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_nonlocal_bind = 1 net.ipv4.ip_forward = 1 EOF sysctl --system # 生效 #时间同步 yum install -y ntpdate timedatectl set-timezone Asia/Shanghai 在kubernetes中service有两种代理模型,一种是基于iptables,另一种是基于ipvs的。ipvs的性能要高于iptables的,但是如果要使用它,需要手动载入ipvs模块。 修改内核参数: cat <<EOF > /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_nonlocal_bind = 1 net.ipv4.ip_forward = 1 EOF sysctl -p /etc/sysctl.d/k8s.conf 1)加载ipvs: [root@k8s-master ~] mkdir /opt/ipvs && cd /opt/ipvs [root@master ipvs] yum -y install ipset ipvsadm sysstat conntrack libseccomp [root@master ipvs] vim ipvs.sh #!/bin/bash modprobe -- ip_vs modprobe -- ip_vs_sh modprobe -- ip_vs_rr modprobe -- ip_vs_wrr modprobe -- nf_conntrack_ipv4 #执行脚本 [root@master ipvs] chmod +x ipvs.sh [root@master ipvs] bash ipvs.sh 2)让脚本开机自启: [root@master ipvs]# lsmod |grep ip_vs [root@master ipvs]# echo "bash /opt/ipvs/ipvs.sh" >> /etc/rc.local [root@master ipvs]# chmod +x /etc/rc.local ``` ##### 1.2.安装docker(每台都执行) ```shell yum -y install yum-utils device-mapper-persistent-data lvm2 yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo yum-config-manager --enable docker-ce-edge yum install -y docker-ce-19.03.9-3.el7 docker-ce-cli-19.03.9-3.el7 containerd.io docker-compose systemctl enable docker systemctl start docker #配置镜像加速(阿里云镜像站) cat > /etc/docker/daemon.json << EOF { "registry-mirrors": ["https://b9pmyelo.mirror.aliyuncs.com"], "exec-opts": ["native.cgroupdriver=systemd"] } EOF #配置重载docker守护进程而不重启容器 (1)vi /etc/docker/daemon.json { "live-restore": true } (2)手动启用该过程 dockerd --live-restore systemd ``` ##### 1.3.安装kubeadm和kubelet(每台都执行) ```shell cat > /etc/yum.repos.d/kubernetes.repo << EOF [kubernetes] name=Kubernetes baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64 enabled=1 gpgcheck=0 repo_gpgcheck=0 gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg EOF yum -y install kubelet-1.23.0-0.x86_64 kubeadm-1.23.0-0.x86_64 kubectl-1.23.0-0.x86_64 systemctl enable kubelet ``` ##### 1.4.使用kubeadm部署master ```shell kubeadm init --kubernetes-version=1.23.0 --apiserver-advertise-address=192.168.1.211 --service-cidr=10.64.0.0/24 --pod-network-cidr=10.244.0.0/16 --image-repository registry.aliyuncs.com/google_containers #注:主机名中不能带有_(下划线),不然初始化会报错 mkdir -p $HOME/.kube cp -i /etc/kubernetes/admin.conf $HOME/.kube/config chown $(id -u):$(id -g) $HOME/.kube/config 查看node信息 kubectl get nodes ``` ##### 1.5.让node加入集群 ```shell #当主节点启动完k8s之后会生成加入节点的命令,视自己服务器而定 kubeadm join 172.16.8.124:6443 --token xxxxx \ --discovery-token-ca-cert-hash xxxxxx #默认token有效期为24小时,当过期之后,该token就不可用了。这时就需要重新创建token,操作如下: kubeadm token create --print-join-command #查看节点是否已加入 kubectl get nodes ``` ##### 1.6.集群组件报错 ###### 1.6.1.所有节点显示 NotReady (是因为还没安装网络组件) ![image-20220407170459496](http://oss.linuxtxc.com/images/image-20220407170459496.png) ```shell #查看组件健康情况 kubectl get cs ``` ![image-20220407170643950](http://oss.linuxtxc.com/images/image-20220407170643950.png) - 解决方法 ```shell vim /etc/kubernetes/manifests/kube-controller-manager.yaml (注释掉 - --port=0) vim /etc/kubernetes/manifests/kube-scheduler.yaml (注释掉 - --port=0) systemctl start kubelet ``` ##### 1.7.安装pod网络插件 ```shell #主节点执行 #kubectl apply -f https://github.com/flannel-io/flannel/blob/master/Documentation/kube-flannel.yml #安装calico # wget https://docs.projectcalico.org/v3.8/getting-started/kubernetes/installation/hosted/kubernetes-datastore/calico-networking/1.7/calico.yaml wget https://install-data.oss-cn-hongkong.aliyuncs.com/deploy/yaml/calico.yaml kubectl apply -f calico.yaml #修改部分 (#取消注释) - name: CALICO_IPV4POOL_CIDR value: "10.244.0.0/16" #地址为初始化集群时的“--pod-network-cidr”的设置IP 查看pods信息 kubectl get pods -n kube-system ``` ##### 1.8.安装私有镜像仓库harbor ```shell #安装docker-compose #可以通过修改URL中的版本,可以自定义您的需要的版本 curl -L https://get.daocloud.io/docker/compose/releases/download/1.21.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose 为安装脚本添加执行权限 chmod +x /usr/local/bin/docker-compose #重启docker systemctl daemon-reload systemctl restart docker #安装harbor #官方下载地址:https://github.com/goharbor/harbor/releases wget https://github.com/goharbor/harbor/releases/download/v2.5.1/harbor-offline-installer-v2.5.1.tgz tar xvf harbor-offline-installer-v2.5.1.tgz cd harbor/ vim harbor.yml (修改默认端口) ./prepare # --with-chartmuseum ,启用chart仓库 ./install.sh --with-chartmuseum #登录harbor (没有证书,需要添加信任) (1)docker login http://192.168.3.124:8080 (docker登录harbor) (docker无法连接harbor时,请在/etc/docker/daemon.json 中添加{ "registry-mirrors": ["https://b9pmyelo.mirror.aliyuncs.com"], "exec-opts": ["native.cgroupdriver=systemd"], "insecure-registries": ["harbor的主机ip:端口"] } (如果还不行请./install.sh) #创建连接镜像仓库的secret kubectl create secret docker-registry harbor-key-secret --docker-server=harbor.linuxtxc.com:9090 --docker-username=admin --docker-password=Harbor123 ``` ##### 1.9.安装coredns ```shell #官方模板:https://github.com/coredns/deployment/blob/master/kubernetes/coredns.yaml.sed #复制内容模板内容 [root@k8s_master yaml]# vim coredns.yaml #要修改的内容 CLUSTER_DNS_IP: 10.0.0.2 #对应kubelet的DNS CLUSTER_DOMAIN: cluster.local REVERSE_CIDRS: in-addr.arpa ip6.arpa STUBDOMAINS: 无 UPSTREAMNAMESERVER: /etc/resolv.conf # 修改镜像为1.7.1 coredns/coredns:1.7.1 #修改后的coredns.yaml wget http://oss.linuxtxc.com/deploy/yaml/coredns.yaml kubectl apply -f coredns.yaml ``` ##### 1.10.重置kubernetes集群 ```shell (master,node都执行) rm -rf ./kube rm -rf /etc/cni/net.d/* (master上执行 ) kubeadm reset kubeadm init --kubernetes-version=1.23.0 --apiserver-advertise-address=192.168.1.211 --service-cidr=10.64.0.0/24 --pod-network-cidr=10.244.0.0/16 --image-repository registry.aliyuncs.com/google_containers mkdir -p $HOME/.kube cp -i /etc/kubernetes/admin.conf $HOME/.kube/config chown $(id -u):$(id -g) $HOME/.kube/config #出现pod无法起来时 #vim /etc/kubernetes/manifests/kube-controller-manager.yaml (注释掉 - --port=0) #vim /etc/kubernetes/manifests/kube-scheduler.yaml (注释掉 - --port=0) #systemctl restart kubelet (node 上执行) kubeadm reset kubeadm join 192.168.3.124:6443 --token f62e1g.exfdrr8bg2fxpdmu \ --discovery-token-ca-cert-hash sha256:7e4762cccce2e8306b6635cbc2091eae34bbf33577276413521a343c49fc026a #安装1.24之后的版本时 rm -rf /etc/containerd/config.toml containerd config default | tee /etc/containerd/config.toml sed -i 's#SystemdCgroup = false#SystemdCgroup = true#g' /etc/containerd/config.toml sed -i 's#sandbox_image = "k8s.gcr.io/pause:3.6"#sandbox_image = "registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.6"#g' /etc/containerd/config.toml systemctl restart containerd ``` ##### 1.11.切换容器引擎为Containerd ```shell #启动模块(默认已经启用) modprobe overlay modprobe br_netfilter #设置必需的 sysctl 参数 cat > /etc/sysctl.d/cri-containerd.conf << EOF net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 EOF sysctl --system #安装containerd (已经安装docker后,默认会有containerd) #yum install -y yum-utils device-mapper-persistent-data lvm2 yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo #yum install -y containerd.io #mkdir -p /etc/containerd #生成默认的配置文件 containerd config default > /etc/containerd/config.toml ``` - 修改配置文件 ​ • pause镜像设置过阿里云镜像仓库地址 ​ • cgroups驱动设置为systemd ​ • 拉取Docker Hub镜像配置加速地址设置为阿里云镜像仓库地址 ```shell sed -i 's#SystemdCgroup = false#SystemdCgroup = true#g' /etc/containerd/config.toml sed -i 's#sandbox_image = "k8s.gcr.io/pause:3.6"#sandbox_image = "registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.6"#g' /etc/containerd/config.toml vim /etc/containerd/config.toml [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] endpoint = ["https://b9pmyelo.mirror.aliyuncs.com"] #修改 #重启containerd systemctl restart containerd ``` - 配置kubelet使用containerd ```shell vi /etc/sysconfig/kubelet KUBELET_EXTRA_ARGS=--container-runtime=remote --container-runtime-endpoint=unix:///run/containerd/containerd.sock --cgroup-driver=systemd systemctl restart kubelet #验证 kubectl get node -o wide ``` ![image-20220531181711832](http://oss.linuxtxc.com/images/image-20220531181711832.png) - 管理容器工具 containerd提供了ctr命令行工具管理容器,但功能比较简单,所以一般会用crictl工具检查和调试容器。 项目地址:https://github.com/kubernetes-sigs/cri-tools/ 设置crictl连接containerd: ```shell vi /etc/crictl.yaml runtime-endpoint: unix:///run/containerd/containerd.sock image-endpoint: unix:///run/containerd/containerd.sock timeout: 10 debug: false ``` - docker与crictl命令对照表: | ***\*镜像相关功能\**** | ***\*Docker\**** | ***\*Containerd\**** | | ---------------------- | ----------------------- | ------------------------ | | 显示本地镜像列表 | docker images | crictl images | | 下载镜像 | docker pull | crictl pull | | 上传镜像 | docker push | 无,例如buildk | | 删除本地镜像 | docker rmi | crictl rmi | | 查看镜像详情 | docker inspect IMAGE-ID | crictl inspecti IMAGE-ID | | ***\*容器相关功能\**** | ***\*Docker\**** | ***\*Containerd\**** | | ---------------------- | ---------------- | -------------------- | | 显示容器列表 | docker ps | crictl ps | | 创建容器 | docker create | crictl create | | 启动容器 | docker start | crictl start | | 停止容器 | docker stop | crictl stop | | 删除容器 | docker rm | crictl rm | | 查看容器详情 | docker inspect | crictl inspect | | 附加容器 | docker attach | crictl attach | | 执行命令 | docker exec | crictl exec | | 查看日志 | docker logs | crictl logs | | 查看容器资源 | docker status | crictl status | | ***\*POD\**** ***\*相关功能\**** | ***\*Docker\**** | ***\*Containerd\**** | | -------------------------------- | ---------------- | -------------------- | | 显示 POD 列表 | 无 | crictl pods | | 查看 POD 详情 | 无 | crictl inspectp | | 运行 POD | 无 | crictl run | | 停止 POD | 无 | crictl stop | ##### 1.12.编写dockerfile - 使用alpine 构建 nginx镜像 ```shell FROM alpine:latest RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories #更换下载地址 RUN apk update && apk --no-cache add gcc libc-dev make openssl-dev pcre-dev zlib-dev linux-headers curl gnupg libxslt-dev gd-dev geoip-dev pcre wget zlib RUN mkdir /opt/apps ADD nginx-1.19.6.tar.gz /usr/local/src/ RUN cd /usr/local/src/nginx-1.19.6 && ./configure --prefix=/opt/apps/nginx --with-http_stub_status_module --with-http_geoip_module --with-http_ssl_module --with-http_gzip_static_module --with-http_v2_module --with-stream --with-stream_ssl_module --user=nginx --group=nginx && make && make install ENV PATH $PATH:/opt/apps/nginx/sbin COPY nginx.conf /opt/apps/nginx/conf/nginx.conf ADD index.html /opt/apps/nginx/html/index.html RUN echo 'if (\$request_filename ~* .*\.(jspx|jsp|z|gz|bz2|7z|zip|rar|tar|tar.gz|tar.bz2|tgz)$) { \ return 403; \ break; \ }' > /opt/apps/nginx/conf/filter.forbid RUN addgroup -g 2019 -S nginx && adduser -s /sbin/nologin -S -D -u 2019 -G nginx nginx RUN mkdir /opt/apps/nginx/conf/vhosts && mkdir -p /opt/logs/nginx && chown -R nginx:nginx /opt/apps/nginx WORKDIR /opt/apps/nginx EXPOSE 80 443 CMD ["nginx", "-g", "daemon off;"] ``` ##### 13.给pod内的etcd集群做数据备份 - 在pod内生成快照,写入周期性计划任务 ```shell * 2 * * * /usr/bin/kubectl exec -it etcd-0 -n apisix -- etcdctl snapshot save /bitnami/etcd/data/member/snap/etcd-`/usr/bin/date +\%Y\%m\%d\%H\%M`.db &> /apps/kubernetes/backup/etcd-0-backup.log * 2 * * * /usr/bin/kubectl exec -it etcd-1 -n apisix -- etcdctl snapshot save /bitnami/etcd/data/member/snap/etcd-`/usr/bin/date +\%Y\%m\%d\%H\%M`.db &> /apps/kubernetes/backup/etcd-1-backup.log * 2 * * * /usr/bin/kubectl exec -it etcd-2 -n apisix -- etcdctl snapshot save /bitnami/etcd/data/member/snap/etcd-`/usr/bin/date +\%Y\%m\%d\%H\%M`.db &> /apps/kubernetes/backup/etcd-2-backup.log ``` - 在node节点上从挂载的pvc中复制到备份目录(写入周期性计划任务中) ```shell 30 2 * * * /usr/bin/find /var/lib/kubelet/pods/d8a02579-3574-4f97-a4e8-ce3fc8c8ab3d/volumes/kubernetes.io~nfs/pvc-47a02205-0a35-48bf-80af-09130d37697/data/memeber/snap -ctime -1 -type f | /usr/bin/xargs -i /usr/bin/cp {} /apps/kubernetes/backup * * * * 7 /usr/bin/find /apps/kubernetes/backup -ctime +15 -type f | /usr/bin/xargs -i /usr/bin/rm -rf {} ``` ----- #### 2.kubernetes 资源管理 ##### 2.1.kubectl create ```shell kubectl create namespace dev #创建一个namespace kubectl create service clusterip ngx-dep --tcp=80:80 #命令行创建service kubectl create -f ns-dev.yaml #根据yaml文件创建资源 kubectl create deployment deploy-nginx --image=nginx:1.17.2 --replicas=3 -n dev #暴露端口 kubectl expose deployment deploy-nginx --port=80 --target-port=80 --type=NodePort --name=nginx-service -n dev #命令行创建yaml模板(–dry-run:不执行命令,打印资源文件,-o yaml,将资源输出为YAML格式) kubectl create deployment deploy-nginx --image=nginx:1.17.2 --replicas=3 -n dev --dry-run=client -o yaml > deploy-nginx.yaml #命令行创建service kubectl create service clusterip ngx-dep --clusterip="none" --tcp=80:80 --dry-run=client -o yaml kubectl create service nodeport nginx-service --tcp=80:80 --dry-run=client -o yaml ``` ##### 2.2.kubectl api-resources ```shell kubectl api-resources #查看k8s所有的资源以及对应的apiversion kubectl api-versions #查看k8s所有 版本号 ``` ##### 2.3.kubectl explain ```shell kubectl explain 资源类型(pod,deployment) # 查看某种资源可以配置的一级配置 kubectl explain 资源类型.属性 #查看资源的子属性 ``` ##### 2.4.kubectl label 版本类标签(release):stable(稳定版)、canary(金丝雀版本,可以将其称之为测试版中的测试版)、beta(测试版); 环境类标签(environment):dev(开发)、qa(测试)、production(生产)、op(运维); 应用类(app):ui、as、pc、sc; 架构类(tier):frontend(前端)、backend(后端)、cache(缓存); 分区标签(partition):customerA(客户A)、customerB(客户B); 品控级别(Track):daily(每天)、weekly(每周)。 ```shell kucectl label pod nginx-pod version=1.0 -n web #为pod打上标签 kubectl label pod --show-labels -n web #显示pod的标签 kucectl label pod nginx-pod version=1.0 --overwrite -n web #覆盖原来的标签 ``` ##### 2.5.kubectl describe ```shell kubectl describe pod nginx-pod -n web #查看pod 的详细信息 kubectl describe service nginx-svc -n web #查看service的 详细信息 kubectl describe node 192.168.3.125 #查看node的详细信息 ``` ##### 2.6.kubectl exec ```shell #进入pod容器中 kubectl exec -it nginx-deployment-798444d598-87hlk -n web /bin/sh ``` ##### 2.7.kubectl get ```shell kubectl get cs #获取集群健康状态 kubectl get csr #查看申请加入kubernetes集群的token信息 kubectl get endpoints -n web #获取service对应的所有pod的访问地址 kubectl get pod -n web -o wide -w #查看namespace web下的pod,--all-namespaces:查看所有namespace下的pod;-w:动态查看;-o wide:查看更多信息 kubectl get pod --show-labels (显示资源标签) kubectl get pod -l app=nginx (-l,根据标签过滤资源) ``` ##### 2.8.kubectl edit ```shell kubectl edit cm kubeadm-config -n kube-system #cm,configMap;编辑configMap中的配置 ``` ##### 2.9.kubectl logs ```shell kubectl logs nginx-deployment-798444d598-87hlk -n web #查看pod日志 kubectl logs -f nginx-deployment-798444d598-87hlk -n web #实时查看日志 kubectl log nginx-deployment-798444d598-87hlk -c <container_name> -n web #查看pod中单个容器的日志 kubectl logs -l app=frontend -n web #返回全部标记为 app=frontend 的 pod 的合并日志 kubectl logs --tail=20 -f nginx-deployment-798444d598-87hlk -n web #过滤时间段的日志 kubectl logs -f -n namespace pod-name --since-time="2021-12-22T02:00:00+00:00" ``` ##### 2.10.kubectl delete ```shell kubectl delete -f deployment-nginx.yaml #删除该yaml中创建的资源 kubectl delete pod nginx-deployment-798444d598-87hlk -n web #删除pod资源 #有部分 Terminating状态的pod无法删除,可以使用 --grace-period=0 --force强制删除 kubectl delete pod calico-kube-controllers-6b77fff45-m6w4n -n kube-system --grace-period=0 --force ``` ##### 2.11.kubectl autoscale ```shell kubectl autoscale deployment deployment-nginx --cpu-percent=60 --min=2 --max=10 #使用 Deployment “deployment-nginx”设定,使用默认的自动伸缩策略,指定目标CPU使用率,使其Pod数量在2到10之间。 ``` ##### 2.12.kubectl patch ```shell #使用(patch)补丁修改、更新资源的字段。 kubectl patch pod rc-nginx-2-kpiqt -p '{"metadata":{"labels":{"app":"nginx-3"}}}' #修改资源配置 ``` ##### 2.13.kubectl replace ```shell kubectl replace -f rc-nginx.yaml #根据yaml文件更新修改后配置资源,会停掉原来的资源,重新创建 ``` ##### 2.14.kubectl scale ``` shell kubectl scale rc redis --replicas=3 -n web #操作pod 的扩容和缩容 kubectl scale --replicas=2 -f redis-slave-deployment.yaml ``` ##### 2.15.kubectl rollout ```shell status:显示当前升级状态 history:显示升级历史记录 pause:暂停版本升级过程 resume:继续已经暂停的版本升级过程 restart:重启版本升级过程 undo:回滚到上一级版本 (可以使用--to-revision,指定版本) kubectl apply -f pc-deployment.yml --record (--record,记录操作记录,便于回滚) 更新镜像: (1)通过kubectl set 命令去更改,nginx为容器名 kubectl set image deploy nginx-deployment nginx=nginx:1.15.2 -n app --record && kubectl rollout pause deployment nginx-deployment -n app #相当于灰度发布 (2)通过修改deployment文件去更改 kubectl apply -f nginx-deployment.yml --record && kubectl rollout pause deployment nginx-deployment -n app #继续更新过程 kubectl rollout resume deployment nginx-deployment -n app #查看历史版本 kubectl rollout history deployment nginx-deployment -n app #版本回滚到v1 kubectl rollout undo deploy nginx-deployment --to-revision=1 -n app ``` ##### 2.16.kubectl taint ```shell kubectl taint node k8s-node1 tag=webapps:PreferNoSchedule #设置污点 kubectl taint node k8s-node1 tag:PreferNoSchedule- #去除污点 kubectl taint node k8s-node1 tag- #去除所有污点 kubectl describe nodes k8s-node1 | grep Taints #查看节点上的污点 #将node标记为不可调度的状态,这样就不会让新创建的pod在此node上运行。 kubectl cordon 192.168.1.48 #恢复node为可调度的状态。 kubectl uncordon 192.168.1.48 #可以让node在维护期间排除节点。drain本意排水,意思是将出问题的node下的pod转移到其它node下运行,并且不接收新的pod。 kubectl drain 192.168.1.48 --ignore-daemonsets --delete-local-data #drain的参数 --force 当一些pod不是经 ReplicationController, ReplicaSet, Job, DaemonSet 或者 StatefulSet 管理的时候 就需要用--force来强制执行 (例如:kube-proxy) --ignore-daemonsets 无视DaemonSet管理下的Pod --delete-local-data 如果有mount local volumn的pod,会强制杀掉该pod并把料清除掉 ``` ##### 2.17.kubectl run ```shell kubectl run nginx --image=nginx:1.17.1 -n web #命令使用镜像创建容器 ``` ##### 2.18.kubectl apply ```shell #如果资源不存在,就创建,相当于kubectl create。 #如果资源存在,就更新,相当于kubectl patch。 kubectl apply -f nginx-pod.yaml -n web --record (--record,记录操作记录,便于回滚) ``` ##### 2.19.kubectl top ```shell kubectl top pod/node -n dev #查看资源使用情况(需要安装metrics-server) #-l,标签选择,--sort-by,根据参数排序 kubectl top pod -l name=cpu-utillzer --sort-by="cpu” -A ``` ##### 2.20.kubectl expose ```shell #将tomcat-deployment 服务的8080 端口 暴露给 tomcat-service 的service (也相当于创建service) kubectl expose deployment tomcat-deployment --port=8080 --target-port=8080 --type=ClusterIP --name=tomcat-service -n app ``` ##### 2.21.kubectl cp ```shell #将pod里的文件拷贝到主机 #kubectl cp -c 容器名 pod名:文件绝对路径 文件目标位置 -n namespace名 kubectl cp nginx-deployment-84b859f76c-crdrl:tmp/helm-v3.5.4-linux-amd64.tar.gz /tmp/helm-v3.5.4-linux-amd64.tar.gz -n app #将主机文件拷贝到pod #kubectl cp 主机文件路径 -c 容器 pod名:容器内绝对路径 -n namespace名 kubectl cp tomcat-java-demo-master.zip nginx-deployment-84b859f76c-crdrl:tmp -n app (如果pod中有多个容器,需要指定进入的容器名) 注:pod后的目录绝对路径不用写"/" ``` ##### 2.22.kubectl certificate ``` #kubectl certificate用来修改证书资源,可选approve/deny同意与拒绝审批。 ``` ##### 2.23.kubectl config ``` #config命令,生成集群信息,集群用户和用户权限并把这些内容写入kubectl读取的配置文件 # 设置集群参数 [root@k8s-master admin]# kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/cert/ca.pem --embed-certs=true --server=${KUBE_APISERVER} --kubeconfig=kubectl.kubeconfig #设置客户端认证参数 [root@k8s-master admin]# kubectl config set-credentials admin --client-certificate=admin.pem --client-key=admin-key.pem --embed-certs=true --kubeconfig=kubectl.kubeconfig #设置上下文参数,包含集群名称和访问集群的用户名字 [root@k8s-master admin]# kubectl config set-context kubernetes --cluster=kubernetes --user=admin --kubeconfig=kubectl.kubeconfig #使用默认上下文 [root@k8s-master admin]# kubectl config use-context kubernetes --kubeconfig=kubectl.kubeconfig ``` ##### 2.24.docker 命令 ```shell #查看容器运行的进程 docker top 容器ID/容器名 #删除所有未被容器使用的镜像 docker image prune -a #删除所有停止运行的容器 docker container prune #删除所有未被挂载的卷 docker volume prune #删除所有未使用的网络 docker network prune #用于清理磁盘,删除关闭的容器、无用的数据卷和网络,以及dangling镜像(即无tag的镜像),-a,清理的更加彻底 docker system prune -a #查看Docker的磁盘使用情况,-v,显示空间使用的详细信息 docker system df -v ``` --- #### 3.kubernetes 的Pod 详解 pod:k8s 最小控制单元,其中包含一个pause容器(又叫infra容器,基础容器),多个业务 容器,提供服务,pod中容器共享网络,存储资源 pause容器作用:可以根据它判断pod的健康状态,同时在pause容器上设置IP,可以让同一个pod中的所有容器共用 - 创建一个pod工作流程: - kubectl向apiserver发送部署请求 - apiserver将工作负载控制器(deployment等)持久化到etcd,etcd和apiserver进行通信 - controller-manager通过watch api监听apiserver,得知新创建的工作负载控制器对象后,将从队列中拉出,根据工作负载控制器的描述挨个创建(rs,rc)等对象,并持久化回到etcd中 - scheduler 调度pod到可用的node节点上,加载namespace。并将pod对下个返回apiserver写入到etcd中 - kubelet收到scheduler调度信息后,将通过容器创建pod ##### 3.1.Pod 所有参数配置 ```yaml apiVersion: v1 kind: Namespace metadata: name: dev --- #所有常用配置参数 apiVersion: v1 #必选,版本号,例如v1 kind: Pod   #必选,资源类型,例如 Pod metadata:   #必选,元数据 name: string #必选,Pod名称 namespace: string #Pod所属的命名空间,默认为"default" labels:    #自定义标签列表 - name: string   spec: #必选,Pod中容器的详细定义 containers: #必选,Pod中容器列表 - name: string #必选,容器名称 image: string #必选,容器的镜像名称 imagePullPolicy: [ Always|Never|IfNotPresent ] #获取镜像的策略 command: [string] #容器的启动命令列表,如不指定,使用打包时使用的启动命令 args: [string] #容器的启动命令参数列表 workingDir: string #容器的工作目录 volumeMounts: #挂载到容器内部的存储卷配置 - name: string #引用pod定义的共享存储卷的名称,需用volumes[]部分定义的的卷名 mountPath: string #存储卷在容器内mount的绝对路径,应少于512字符 readOnly: boolean #是否为只读模式 ports: #需要暴露的端口库号列表 - name: string #端口的名称 containerPort: int #容器需要监听的端口号 hostPort: int #容器所在主机需要监听的端口号,默认与Container相同 protocol: string #端口协议,支持TCP和UDP,默认TCP env: #容器运行前需设置的环境变量列表 - name: string #环境变量名称 value: string #环境变量的值 resources: #资源限制和请求的设置 limits: #资源限制的设置 cpu: string #Cpu的限制,单位为core数 memory: string #内存限制,单位可以为Mib/Gib requests: #资源请求的设置 cpu: string #Cpu请求,容器启动的初始可用数量 memory: string #内存请求,容器启动的初始可用数量 lifecycle: #生命周期钩子 postStart: #容器启动后立即执行此钩子,如果执行失败,会根据重启策略进行重启 preStop: #容器终止前执行此钩子,无论结果如何,容器都会终止 livenessProbe: #对Pod内各容器健康检查的设置,当探测无响应几次后将自动重启该容器 exec:   #对Pod容器内检查方式设置为exec方式 command: [string] #exec方式需要制定的命令或脚本 httpGet: #对Pod内个容器健康检查方法设置为HttpGet,需要制定Path、port path: string port: number host: string scheme: string HttpHeaders: - name: string value: string tcpSocket: #对Pod内个容器健康检查方式设置为tcpSocket方式 port: number initialDelaySeconds: 0 #容器启动完成后首次探测的时间,单位为秒 timeoutSeconds: 0    #对容器健康检查探测等待响应的超时时间,单位秒,默认1秒 periodSeconds: 0    #对容器监控检查的定期探测时间设置,单位秒,默认10秒一次 successThreshold: 0 failureThreshold: 0 securityContext: privileged: false restartPolicy: [Always | Never | OnFailure] #Pod的重启策略 nodeName: <string> #设置NodeName表示将该Pod调度到指定到名称的node节点上 nodeSelector: obeject #设置NodeSelector表示将该Pod调度到包含这个label的node上 imagePullSecrets: #Pull镜像时使用的secret名称,以key:secretkey格式指定 - name: string hostNetwork: false #是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络 volumes: #在该pod上定义共享存储卷列表 - name: string #共享存储卷名称 (volumes类型有很多种) emptyDir: {} #类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录。为空值 hostPath: string #类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录 path: string    #Pod所在宿主机的目录,将被用于同期中mount的目录 secret:    #类型为secret的存储卷,挂载集群与定义的secret对象到容器内部 scretname: string items: - key: string path: string configMap: #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部 name: string items: - key: string path: string ``` ###### 3.1.1.环境变量ENV - 创建容器时,为容器设置环境变量 - - **应用场景:** • 容器内应用程序希望获取Pod信息 • 容器内应用程序希望通过用户定义的变量改变默认行为 **变量值几种定义方式:** • 自定义变量值 • 变量值从Pod属性获取 • 变量值从Secret、ConfigMap获取 ```yaml apiVersion: v1 kind: Pod metadata: name: pod-envars spec: containers: - name: test-container image: busybox command: [ "sh", "-c","sleep 3600h"] env: #变量值从Pod属性获取 - name: MY_NODE_NAME valueFrom: fieldRef: fieldPath: spec.nodeName - name: MY_POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: MY_POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: MY_POD_IP valueFrom: fieldRef: fieldPath: status.podIP #自定义变量值 - name: PASSWORD value: qwer123 ``` ##### 3.2.Pod资源限制 - limits 限制容器最高使用多少资源,requests 容器使用的最小资源申请(对于k8s来说是预留,主要用作k8s对node资源一个规划和分配)。 - requests一般小于limits的20%-30%。 - limits建议不能超出宿主机配置,否则没意义了,至少要低于宿主机配置的20% - requests必须小于或等于limits。 - k8s会根据requests的值去查找能满足该值的node进行调度,如果不满足,pod处于未分配创建。 - requests决定了一个节点分配的pod数量,所以不要设置太大,否则会造成node资源浪费,即跑的pod少,实际负载很低。 - kubectl describe node k8s-node2 查看节点资源分配情况。 ```yaml apiVersion: v1 kind: Pod metadata: name: test-pod namespace: app labels: app: nginx spec: containers: - name: nginx01 # 容器名称 image: nginx:1.17.1 # 容器需要的镜像地址 imagePullPolicy: IfNotPresent # 设置镜像拉取策略,Alawys;IfNotPresent;Never ports: # 端口设置 - containerPort: 80 # 容器要监听的端口 (0~65536) protocol: TCP # 端口协议 resources: # 资源配额 limits: # 限制资源的上限 cpu: "1" # CPU限制,单位是core数,0.1=100m memory: "10Gi" # 内存限制 requests: # 限制资源的下限 cpu: "0.5" # CPU限制,单位是core数, 0.5=500m memory: "1Gi" # 内存限制 ``` - imagePullPolicy:用于设置镜像拉取的策略,kubernetes支持配置三种拉取策略: - Always:总是从远程仓库拉取镜像(一直远程下载)。 - IfNotPresent:本地有则使用本地镜像,本地没有则从远程仓库拉取镜像(本地有就用本地,本地没有就使用远程下载)。 - Never:只使用本地镜像,从不去远程仓库拉取,本地没有就报错(一直使用本地,没有就报错)。 ##### 3.3.Pod 生命周期 我们一般将Pod对象从创建到终止的这段时间范围称为Pod的生命周期,它主要包含下面的过程: - Pod创建过程。 - 运行初始化容器(init container)过程,执行一些主容器的前置工作,执行完就结束。 - **应用场景:** - 环境检查:例如确保应用容器依赖的服务启动后再启动应用容器 - 初始化配置:例如给应用容器准备配置文件 - 运行主容器(main container): - 容器启动后钩子(post start)。 - 容器的存活性探测(liveness probe)、就绪性探测(readiness probe)。 - 容器终止前钩子(pre stop)。 - Pod终止过程。 ###### 3.3.1.钩子函数 - 钩子函数能够感知自身生命周期中的事件,并在相应的时刻到来时运行用户指定的程序代码。 - kubernetes在主容器启动之后和停止之前提供了两个钩子函数: - post start:容器创建之后执行,如果失败会重启容器。 - pre stop:容器终止之前执行,执行完成之后容器将成功终止,在其完成之前会阻塞删除容器的操作。 - 钩子处理器支持使用下面的三种方式定义动作: - ① exec命令:在容器内执行一次命令。 ```yaml …… lifecycle: postStart: exec: command: - cat - /tmp/healthy …… ``` ​ ② tcpSocket:在当前容器尝试访问指定的socket。 ```yaml …… lifecycle: postStart: tcpSocket: port: 8080 …… ``` ​ ③ httpGet:在当前容器中向某url发起HTTP请求。 ```yaml …… lifecycle: postStart: httpGet: path: / #URI地址 port: 80 #端口号 host: 192.168.109.100 #主机地址 scheme: HTTP #支持的协议,http或者https …… ``` 以exec方式为例,演示下钩子函数的使用,创建pod-hook-exec.yaml文件,内容如下: ```yaml apiVersion: v1 kind: Pod metadata: name: pod-hook-exec namespace: app labels: app: nginx spec: containers: # 容器配置 - name: nginx image: nginx:1.17.1 imagePullPolicy: IfNotPresent ports: - name: nginx-port containerPort: 80 protocol: TCP resources: limits: cpu: "2" memory: "10Gi" requests: cpu: "1" memory: "10Mi" lifecycle: # 生命周期配置 postStart: # 容器创建之后执行,如果失败会重启容器 exec: # 在容器启动的时候,执行一条命令,修改掉Nginx的首页内容 command: ["/bin/sh","-c","echo postStart ... > /usr/share/nginx/html/index.html"] preStop: # 容器终止之前执行,执行完成之后容器将成功终止,在其完成之前会阻塞删除容器的操作 exec: # 在容器停止之前停止Nginx的服务 command: ["/usr/sbin/nginx","-s","quit"] ``` ###### 3.3.2.容器探针 - 容器探测用于检测容器中的应用实例是否正常工作,是保障业务可用性的一种传统机制。 - liveness probes:存活性探测,用于检测应用实例当前是否处于正常运行状态,如果不是,k8s会重启容器。 - readiness probes:就绪性探测,用于检测应用实例是否可以接受请求,如果不能,k8s不会转发流量,并将容器从service中剔除。 - 上面两种探针目前均支持三种探测方式: - ① exec命令:在容器内执行一次命令,如果命令执行的退出码为0,则认为程序正常,否则不正常。 ```yaml ---------------------------- readinessProbe: exec: command: - cat - /etc/hosts initialDelaySeconds: 5 timeoutSeconds: 2 successThreshold: 3 failureThreshold: 2 periodSeconds: 5 ----------------------------- ``` ② tcpSocket:将会尝试访问一个用户容器的端口,如果能够建立这条连接,则认为程序正常,否则不正常。 ```yaml …… livenessProbe: tcpSocket: port: 8080 failureThreshold: 5 #检测失败5次表示未就绪 initialDelaySeconds: 60 #初始化时间 periodSeconds: 10 #检测间隔 successThreshold: 1 #检查成功为1次表示就绪,存活和启动探测的这个值必须是 1 timeoutSeconds: 5 #检测超时5秒表示未就绪 …… ``` - ③ httpGet:调用容器内web应用的URL,如果返回的状态码在200和399之前,则认为程序正常,否则不正常。 ```yaml ------------------------ livenessProbe: #健康检查方式:[readinessProbe,livenessProbe,StartupProbe] httpGet: #请求方式 path: /health #请求路径 port: 8080 #请求端口 scheme: HTTP ##请求协议 failureThreshold: 5 #检测失败5次表示未就绪 initialDelaySeconds: 60 #初始化时间 periodSeconds: 10 #检测间隔 successThreshold: 1 #检查成功为1次表示就绪,存活和启动探测的这个值必须是 1 timeoutSeconds: 5 #检测超时5秒表示未就绪 ---------------------------- ``` - startupProbe : 启动探测,k8s1.16版本后新加的探测方式,用于判断容器内应用程序是否已经启动,如果配置了startuprobe,就会先禁用其他的探测,直到它成功为止。 ```yaml ---------------------------------- startupProbe: #健康检查方式:[readinessProbe,livenessProbe,StartupProbe] httpGet: #请求方式 path: / #请求路径 port: 8080 #请求端口 scheme: HTTP #请求协议 failureThreshold: 3 #检测失败3次表示未就绪 periodSeconds: 10 #检测间隔 successThreshold: 1 #检查成功为1次表示就绪,存活和启动探测的这个值必须是 1 timeoutSeconds: 1 #检测超时1秒表示未就绪 ---------------------------------- ``` initialDelaySeconds # 容器启动后等待多少秒执行第一次探测。 timeoutSeconds # 探测超时时间。默认1秒,最小1秒。 periodSeconds # 执行探测的频率。默认是10秒,最小1秒。 failureThreshold # 连续探测失败多少次才被认定为失败。默认是3。最小值是1。 successThreshold # 连续探测成功多少次才被认定为成功。默认是1,存活和启动探测的这个值必须是 1。 - 重启策略: - Always:容器失效时,自动重启该容器,默认值。 - OnFailure:容器终止运行且退出码不为0时重启。 - Never:不论状态如何,都不重启该容器。 - readinessProbe+ livenessProbe混合案例 ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: probe-deployment namespace: app spec: replicas: 2 revisionHistoryLimit: 10 #可保留的版本数 minReadySeconds: 5 #在等待设置的时间后才进行升级 strategy: #策略 type: RollingUpdate rollingUpdate: #滚动更新 maxSurge: 30% #最大额外可以存在的副本数,可以为百分比,也可以为整数; 默认25% maxUnavailable: 30% #最大不可用状态的 ;Pod 的最大值,可以为百分比,也可以为整数,默认25% selector: matchLabels: project: dev app: nginx template: metadata: labels: project: dev app: nginx spec: containers: - name: nginx image: nginx:1.17.3 resources: # 资源配额 limits: # 限制资源的上限 cpu: "1" # CPU限制,单位是core数,0.1=100m memory: "100Mi" # 内存限制 requests: # 限制资源的下限 cpu: "0.5" # CPU限制,单位是core数, 0.5=500m memory: "50Mi" # 内存限制 livenessProbe: #存活性检查,重启容器 httpGet: path: / port: 80 initialDelaySeconds: 5 ##初始化时间,多少秒后开始第一次检测 timeoutSeconds: 1 #检测超时1秒表示未就绪,默认1秒,最小1秒 periodSeconds: 10 #执行探测的频率,默认是10秒,最小1秒 failureThreshold: 5 #检测失败5次表示未就绪,默认是3 successThreshold: 1 #检查成功为1次表示就绪,默认是1,存活和启动探测的这个值必须是 1 readinessProbe: #就绪性探测,从service中剔除容器 httpGet: path: / port: 80 initialDelaySeconds: 5 ##初始化时间,多少秒后开始第一次检测 timeoutSeconds: 1 #检测超时1秒表示未就绪,默认1秒,最小1秒 periodSeconds: 10 #执行探测的频率,默认是10秒,最小1秒 failureThreshold: 5 #检测失败5次表示未就绪,默认是3 successThreshold: 3 #检查成功为2次表示就绪,默认是1 ``` ---- #### 4.kubernetes 中Pod调度 - kubernetes提供了四大类调度方式。 - 自动调度:运行在哪个Node节点上完全由Scheduler经过一系列的算法计算得出。 - 定向调度:NodeName、NodeSelector。 - 亲和性调度:NodeAffinity、PodAffinity、PodAntiAffinity。 - 污点(容忍)调度:Taints、Toleration。 ##### 4.1.定向调度 - 定向调度,指的是利用在Pod上声明的nodeName或nodeSelector,以此将Pod调度到期望的Node节点上。注意,这里的调度是强制的,这就意味着即使要调度的目标Node不存在,也会向上面进行调度,只不过Pod运行失败而已。 nodeName:用于强制约束将Pod调度到指定的name的Node节点上。这种方式,其实是直接跳过Scheduler的调度逻辑,直接将Pod调度到指定名称的节点。 - 创建一个pod-nodename.yaml文件,内容如下: ```yaml apiVersion: v1 kind: Pod metadata: name: pod-nodename namespace: web labels: app: nginx spec: containers: # 容器配置 - name: nginx image: nginx:1.17.1 imagePullPolicy: IfNotPresent ports: - name: nginx-port containerPort: 80 protocol: TCP nodeName: k8s-node1 #指定调度到k8s-node1节点上 ``` nodeSelector:用于将Pod调度到添加了指定标签的Node节点上,它是通过kubernetes的label-selector机制实现的,换言之,在Pod创建之前,会由Scheduler使用MatchNodeSelector调度策略进行label匹配,找出目标node,然后将Pod调度到目标节点,该匹配规则是强制约束。 ```shell #给node节点添加标签 kubectl label node k8s-node1 node=web kubectl label node k8s-node2 node=app ``` - 创建pod-nodeselector.yaml文件,内容如下: ```yaml apiVersion: v1 kind: Pod metadata: name: pod-nodeselector namespace: app spec: containers: # 容器配置 - name: nginx image: nginx:1.17.1 imagePullPolicy: IfNotPresent ports: - name: nginx-port containerPort: 80 protocol: TCP nodeSelector: node: app #指定调度到具有node=app的Node节点上 ``` ##### 4.2.亲和性调度 - 虽然定向调度的两种方式,使用起来非常方便,但是也有一定的问题,那就是如果没有满足条件的Node,那么Pod将不会被运行,即使在集群中还有可用的Node列表也不行,这就限制了它的使用场景。 - 基于上面的问题,kubernetes还提供了一种亲和性调度(Affinity)。它在nodeSelector的基础之上进行了扩展,可以通过配置的形式,实现优先选择满足条件的Node进行调度,如果没有,也可以调度到不满足条件的节点上,使得调度更加灵活。 - Affinity主要分为三类: - nodeAffinity(node亲和性):以Node为目标,解决Pod可以调度到哪些Node的问题。 - podAffinity(pod亲和性):以Pod为目标,解决Pod可以和那些已存在的Pod部署在同一个拓扑域中的问题。 - podAntiAffinity(pod反亲和性):以Pod为目标,解决Pod不能和那些已经存在的Pod部署在同一拓扑域中的问题。 ###### 4.2.1.node亲和性(nodeAffinity) - 查看nodeAffinity的可选配置项: ```yaml pod.spec.affinity.nodeAffinity requiredDuringSchedulingIgnoredDuringExecution #Node节点必须满足指定的所有规则才可以,相当于硬限制 nodeSelectorTerms #节点选择列表 matchFields   #按节点字段列出的节点选择器要求列表   matchExpressions   #按节点标签列出的节点选择器要求列表(推荐) key   #键   values #值   operator # 关系符 支持Exists, DoesNotExist, In, NotIn, Gt, Lt --- preferredDuringSchedulingIgnoredDuringExecution #优先调度到满足指定的规则的Node,相当于软限制 (倾向) preference #一个节点选择器项,与相应的权重相关联 matchFields #按节点字段列出的节点选择器要求列表 matchExpressions #按节点标签列出的节点选择器要求列表(推荐)   key #键   values #值     operator #关系符 支持In, NotIn, Exists, DoesNotExist, Gt, Lt weight #倾向权重,在范围1-100。 --- - matchExpressions: - key: nodeenv # 匹配存在标签的key为nodeenv的节点 operator: Exists - key: nodeenv # 匹配标签的key为nodeenv,且value是"xxx"或"yyy"的节点 operator: In values: ["xxx","yyy"] - key: nodeenv # 匹配标签的key为nodeenv,且value大于"xxx"的节点 operator: Gt values: "xxx" ``` - 下面演示preferredDuringSchedulingIgnoredDuringExecution(软限制): - 创建pod-nodeaffinity-preferred.yaml文件,内容如下: ```yaml apiVersion: v1 kind: Pod metadata: name: pod-nodeaffinity-preferred namespace: app spec: containers: # 容器配置 - name: nginx image: nginx:1.17.1 imagePullPolicy: IfNotPresent ports: - name: nginx-port containerPort: 80 protocol: TCP affinity: # 亲和性配置 nodeAffinity: # node亲和性配置 preferredDuringSchedulingIgnoredDuringExecution: # 先匹配node标签中有nodeenv=app或者nodeenv=xyy的node,优先调度到满足指定的规则的Node,相当于软限制 (倾向) - preference: # 一个节点选择器项,与相应的权重相关联 matchExpressions: - key: nodeenv operator: In values: - "app" - "xyy" weight: 50 ``` - 下面演示preferredDuringSchedulingIgnoredDuringExecution(硬限制): - 创建pod-nodeaffinity-preferred.yaml文件,内容如下: ```yaml apiVersion: v1 kind: Pod metadata: name: pod-nodeaffinity-required namespace: dev spec: containers: # 容器配置 - name: nginx image: nginx:1.17.1 imagePullPolicy: IfNotPresent ports: - name: nginx-port containerPort: 80 protocol: TCP affinity: # 亲和性配置 nodeAffinity: # node亲和性配置 requiredDuringSchedulingIgnoredDuringExecution: #先匹配node标签中有nodeenv=app或者nodeenv=xyy的node,如果没有,则会调度失败,相当于硬规则,类似于定向调度 nodeSelectorTerms: # 节点选择列表 - matchExpressions: - key: nodeenv # 匹配存在标签的key为nodeenv的节点,并且value是"xxx"或"yyy"的节点 operator: In values: - "app" - "yyy" ``` nodeAffinity的注意事项: - 如果同时定义了nodeSelector和nodeAffinity,那么必须两个条件都满足,Pod才能运行在指定的Node上。 - 如果nodeAffinity指定了多个nodeSelectorTerms,那么只需要其中一个能够匹配成功即可。 - 如果一个nodeSelectorTerms中有多个matchExpressions,则一个节点必须满足所有的才能匹配成功。 - 如果一个Pod所在的Node在Pod运行期间其标签发生了改变,不再符合该Pod的nodeAffinity的要求,则系统将忽略此变化。 ###### 4.2.2.Pod亲和性(PodAffinity) - PodAffinity的可选配置项: ```yaml pod.spec.affinity.podAffinity requiredDuringSchedulingIgnoredDuringExecution #硬限制 namespaces #指定参照pod的namespace topologyKey #指定调度作用域 labelSelector # 标签选择器 matchExpressions #按节点标签列出的节点选择器要求列表(推荐)   key   #键   values #值   operator #关系符 支持In, NotIn, Exists, DoesNotExist.     matchLabels   #指多个matchExpressions映射的内容   preferredDuringSchedulingIgnoredDuringExecution #软限制   podAffinityTerm #选项     namespaces #指定参照pod的namespace topologyKey #指定调度作用域 labelSelector # 标签选择器  matchExpressions    key   # 键      values # 值    operator  matchLabels weight # 倾向权重,在范围1-100 #topologyKey用于指定调度的作用域,例如: #如果指定为kubernetes.io/hostname,那就是以Node节点为区分范围。 #如果指定为beta.kubernetes.io/os,则以Node节点的操作系统类型来区分。 ``` - 创建Pod过程: - 创建pod-podaffinity-requred.yaml文件,内容如下: ```yaml apiVersion: v1 kind: Pod metadata: name: pod-podaffinity-requred namespace: app spec: containers: # 容器配置 - name: nginx image: nginx:1.17.1 imagePullPolicy: IfNotPresent ports: - name: nginx-web containerPort: 80 protocol: TCP affinity: # 亲和性配置 podAffinity: # Pod亲和性 requiredDuringSchedulingIgnoredDuringExecution: # 硬限制 - labelSelector: matchExpressions: # 该Pod必须和拥有标签app=nginx或者app=test的Pod在同一个Node上。 - key: app operator: In values: - "nginx" - "test" topologyKey: kubernetes.io/hostname ``` - 创建Pod过程: - 创建pod-podaffinity- prefer.yaml文件,内容如下: ```yaml apiVersion: v1 kind: Pod metadata: name: pod-podaffinity-prefer namespace: app spec: containers: # 容器配置 - name: nginx01 image: nginx:1.17.1 imagePullPolicy: IfNotPresent ports: - name: nginx-app containerPort: 80 protocol: TCP affinity: # 亲和性配置 podAffinity: # Pod亲和性 preferredDuringSchedulingIgnoredDuringExecution: #软限制 - weight: 50 podAffinityTerm: labelSelector: matchExpressions: #先匹配拥有标签app=yyy或者app=test的Pod,如果有,则将pod放在匹配pod同一个Node上,如果没有则让Scheduler根据算法自动调度 - key: app operator: In values: - "yyy" - "test" topologyKey: kubernetes.io/hostname ``` ###### 4.2.3.Pod反亲和性(podAntiAffinity) - 主要实现以运行的Pod为参照,让新创建的Pod和参照的Pod不在一个区域的功能。 ```yaml apiVersion: v1 kind: Pod metadata: name: pod-podantiaffinity-requred namespace: app spec: containers: # 容器配置 - name: nginx image: nginx:1.17.1 imagePullPolicy: IfNotPresent ports: - name: nginx-port containerPort: 80 protocol: TCP affinity: # 亲和性配置 podAntiAffinity: # Pod反亲和性 requiredDuringSchedulingIgnoredDuringExecution: # 硬限制 - labelSelector: matchExpressions: - key: app operator: In values: - "nginx" topologyKey: kubernetes.io/hostname ``` ##### 4.3.污点和容忍 ###### 4.3.1.污点(Taints) - Node被设置了污点之后就和Pod之间存在了一种相斥的关系,进而拒绝Pod调度进来,甚至可以将已经存在的Pod驱逐出去。 - 污点的格式为:`key=value:effect`,key和value是污点的标签,effect描述污点的作用,支持如下三个选项: - PreferNoSchedule:kubernetes将尽量避免把Pod调度到具有该污点的Node上,除非没有其他节点可以调度。 - NoSchedule:kubernetes将不会把Pod调度到具有该污点的Node上,但是不会影响当前Node上已经存在的Pod。 - NoExecute:kubernetes将不会把Pod调度到具有该污点的Node上,同时也会将Node上已经存在的Pod驱逐。 ```shell #设置污点 kubectl taint node xxx key=value:effect #去除污点 kubectl taint node xxx key:effect- #去除所有污点 kubectl taint node xxx key- #查询所有节点的污点 wget -O jq https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64 chmod +x ./jq cp jq /usr/bin kubectl get nodes -o json | jq '.items[].spec' #查看所有节点上的污点 kubectl describe node | grep Taint #给k8s-node1节点设置污点(PreferNoSchedule) kubectl taint node k8s-node1 tag=test:PreferNoSchedule #为k8s-node1取消污点(PreferNoSchedule),并设置污点(NoSchedule) kubectl taint node k8s-node1 tag:PreferNoSchedule- kubectl taint node k8s-node1 tag=test:NoSchedule ``` ###### 4.3.2.容忍 污点是拒绝,容忍就是忽略,Node通过污点拒绝Pod调度上去,Pod通过容忍忽略拒绝 - 容忍的详细配置: ```shell kubectl explain pod.spec.tolerations ......... tolerations - key       # 对应着要容忍的污点的键,空意味着匹配所有的键 value     # 对应着要容忍的污点的值 operator  # key-value的运算符,支持Equal(默认)和Exists effect    # 对应污点的effect,空意味着匹配所有影响 tolerationSeconds   # 容忍时间, 当effect为NoExecute时生效,表示pod在Node上的停留时间 ``` 当operator为Equal的时候,如果Node节点有多个Taint,那么Pod每个Taint都需要容忍才能部署上去。 当operator为Exists的时候,有如下的三种写法: - 容忍指定的污点,污点带有指定的effect: - 容忍指定的污点,不考虑具体的effect: - 容忍一切污点(慎用): ```yaml tolerations: # 容忍 - key: "tag" # 要容忍的污点的key operator: Exists # 操作符 effect: NoExecute # 添加容忍的规则,这里必须和标记的污点规则相同 ``` ```yaml tolerations: # 容忍 - key: "tag" # 要容忍的污点的key operator: Exists # 操作符 ``` ```yaml tolerations: # 容忍 - operator: Exists # 操作符 ``` - 创建pod-toleration.yaml文件,内容如下: ```yaml apiVersion: v1 kind: Pod metadata: name: pod-toleration namespace: dev spec: containers: # 容器配置 - name: nginx image: nginx:1.17.1 imagePullPolicy: IfNotPresent ports: - name: nginx-port containerPort: 80 protocol: TCP tolerations: # 容忍 - key: "tag" # 要容忍的污点的key operator: Equal # 操作符 value: "test" # 要容忍的污点的value effect: NoExecute # 添加容忍的规则,这里必须和标记的污点规则相同 ``` - 案例: ```shell #给两个节点都打上污点 kubectl taint node 192.168.3.125 tag=test:NoSchedule kubectl taint node 192.168.3.125 tag=deploy:NoSchedule vim pod-toleration-test.yaml apiVersion: v1 kind: Pod metadata: name: pod-toleration namespace: dev spec: containers: # 容器配置 - name: nginx image: nginx:1.17.1 imagePullPolicy: IfNotPresent ports: - name: nginx-port containerPort: 80 protocol: TCP tolerations: # 容忍 - key: "tag" # 要容忍的污点的key operator: Equal # 操作符 value: "test" # 要容忍的污点的value effect: NoSchedule # 添加容忍的规则,这里必须和标记的污点规则相同 - key: "tag" # 要容忍的污点的key operator: Equal # 操作符 value: "deploy" # 要容忍的污点的value effect: NoExecute # 添加容忍的规则,这里必须和标记的污点规则相同 ``` ---- #### 5.kubernetes的Pod控制器 ##### 5.1.Deployment控制器 - Deployment控制器并不直接管理Pod,而是通过管理ReplicaSet来间接管理Pod,即:Deployment管理ReplicaSet,ReplicaSet管理Pod。 - Deployment的主要功能如下: - 支持ReplicaSet的所有功能。 - 支持发布的停止、继续。 - 支持版本滚动更新和版本回退。 - 创建nginx-deployment.yaml文件,在spec下添加更新策略 ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment namespace: app spec: replicas: 3 revisionHistoryLimit: 10 #可保留的版本数 minReadySeconds: 5 #在等待设置的时间后才进行升级 strategy: #策略 type: RollingUpdate rollingUpdate: #滚动更新,就是杀死一部分,就启动一部分,在更新过程中,存在两个版本的Pod maxSurge: 30% #最大额外可以存在的副本数,可以为百分比,也可以为整数; 默认25% maxUnavailable: 30% #最大不可用状态的 ;Pod 的最大值,可以为百分比,也可以为整数,默认25% selector: matchLabels: app: nginx #matchExpressions: # Expressions匹配规则 # - {key: app, operator: In, values: [nginx-pod]} template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.17.1 imagePullpolicy: ifnotpresent ports: - containerPort: 80 ``` - 案例 ```yaml apiVersion: apps/v1 kind: Deployment metadata: labels: app: java-demo name: java-demo spec: replicas: 1 selector: matchLabels: app: java-demo template: metadata: labels: app: java-demo spec: imagePullSecrets: - name: harbor-key-secret containers: - image: harbor.linuxtxc.com:9090/txcrepo/tomcat-demo:v1 name: java-demo resources: limits: cpu: 1 memory: 1Gi requests: cpu: 0.7 memory: 700Mi livenessProbe: #存活检查:检查时间,将杀死容器,根据restartPolicy操作 httpGet: path: / port: 8080 initialDelaySeconds: 60 #容器启动后60秒启动健康检查 periodSeconds: 30 #隔30秒检查一次 readinessProbe: #就绪检查:检查失败,k8s会将pod从service,endpoints剔除 httpGet: path: / port: 8080 initialDelaySeconds: 60 #容器启动后60秒启动健康检查 periodSeconds: 30 #隔30秒检查一次 volumeMounts: - name: config #要和下面的volumes名字一样 mountPath: "/usr/local/tomcat/webapps/ROOT/WEB-INF/classes/application.yml" #容器内路径 subPath: application.yml #防止被configmap覆盖掉容器内目录下的其他文件 volumes: - name: config #要和上面的volumeMounts名字一样 configMap: name: java-demo-config items: - key: "application.yml" path: "application.yml" ``` - 镜像更新 ```shell (1)kubectl set image deployment nginx-deployment nginx=nginx:1.17.2 -n app (2)或者修改 nginx-deployment.yaml 中的image,再使用kubectl apply -f nginx-deployment.yaml --recard 更新资源 (3)kubectl edit deployment nginx-deployment -n app ,直接使用命令修改deployment #查看升级过程 kubectl get pod -n app -w ``` ![image-20220312150808108](http://oss.linuxtxc.com/images/image-20220312150808108.png) - 查看rs,发现原来的rs依旧存在,只是Pod的数量变为0,而后又产生了一个rs,Pod的数量变为3 ```shell kubectl get rs -n app ``` ![image-20220312151030643](http://oss.linuxtxc.com/images/image-20220312151030643.png) - 查看历史版本 ```shell kubectl rollout history deployment -n app ``` ![image-20220312152424542](http://oss.linuxtxc.com/images/image-20220312152424542.png) - 版本回滚 ``` kubectl rollout undo deploy nginx-deployment --to-revision=1 -n app ``` - 金丝雀发布(在一批新的Pod资源创建完成后立即暂停更新过程) ```shell (1)kubectl set image deploy nginx-deployment nginx=nginx:1.17.3 -n app && kubectl rollout pause deployment nginx-deployment -n app (2)kubectl apply -f nginx-deployment.yml --record && kubectl rollout pause deployment nginx-deployment -n app ``` ##### 5.2.Horizontal Pod Autoscaler(HPA) HPA可以获取每个Pod的利用率,然后和HPA中定义的指标进行对比,同时计算出需要伸缩的具体值,最后实现Pod的数量的调整。 ###### 5.2.1.安装metrics-server(用来收集集群中的资源使用情况。) ```shell #wget https://github.com/kubernetes-sigs/metrics-server/archive/v0.3.6.tar.gz wget http://oss.linuxtxc.com/metrics-server.zip #解压 unzip metrics-server.zip #进入metrics-server/deploy/1.8+/目录 cd metrics-server/deploy/1.8+ #修改metrics-server-deployment.yaml文件 vim metrics-server-deployment.yaml 按图中添加下面选项 hostNetwork: true image: registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server-amd64:v0.3.6 args: - --kubelet-insecure-tls - --kubelet-preferred-address-types=InternalIP,Hostname,InternalDNS,ExternalDNS,ExternalIP ``` ![image-20220312164723469](http://oss.linuxtxc.com/images/image-20220312164723469.png) - 安装安装metrics-server(v0.4.1) ```shell wget https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.4.1/components.yaml 修改components.yaml 修改部分: - --kubelet-insecure-tls image: registry.cn-shanghai.aliyuncs.com/xuweiwei-kubernetes/metrics-server:v0.4.1 ``` ![image-20220312183606595](http://oss.linuxtxc.com/images/image-20220312183606595.png) - 查看metrics-server生成的Pod: ```shell kubectl get pod -n kube-system ``` ![image-20220312165123704](http://oss.linuxtxc.com/images/image-20220312165123704.png) ###### 5.2.2.错误排查 - 查看资源使用情况报错 ![image-20220312165514330](http://oss.linuxtxc.com/images/image-20220312165514330.png) - 排查错误 ```shell systemctl status kube-apiserver -l #或者 journalctl -u kube-apiserver ``` ![image-20220312173924651](http://oss.linuxtxc.com/images/image-20220312173924651.png) - metric-server安装要满足2个条件 - 在master节点要能访问metrics server pod ip(kubeadm部署默认已经满足该条件,二进制部署需注意要在master节点也部署node组件) - apiserver启用聚合层支持(kubeadm默认已经启用,二进制部署需自己启用) 因为我是二进制安装的,所以在master上安装node组件就可以了 ``` kubectl top pod -n app ``` ![image-20220312182326385](http://oss.linuxtxc.com/images/image-20220312182326385.png) ###### 5.2.3.部署HPA案例 - 使用之前创建的nginx-deployment,使用kubectl edit 将副本数改为 1 ![image-20220312184814408](http://oss.linuxtxc.com/images/image-20220312184814408.png) - 创建 nginx-service.yaml ``` apiVersion: v1 kind: Service metadata: name: nginx-service namespace: app spec: selector: # 标签选择器,用于确定当前Service代理那些Pod app: nginx-deployment type: NodePort ports: # - port: 80 # Service端口 protocol: TCP targetPort : 80 nodePort: 30081 ``` - 创建nginx-hpa.yaml ```yaml apiVersion: autoscaling/v1 # 版本号 kind: HorizontalPodAutoscaler # 类型 metadata: # 元数据 name: nginx-hpa # deployment的名称 namespace: app #命名类型 spec: minReplicas: 1 # 最小Pod数量 maxReplicas: 10 # 最大Pod数量 targetCPUUtilizationPercentage: 3 # CPU使用率指标 scaleTargetRef: # 指定要控制的Nginx的信息 apiVersion: apps/v1 kind: Deployment name: nginx-deployment ``` ```shell #使用命令创建HPA控制器 kubectl autoscale deployment nginx-hpa --cpu-percent=3 --min=1 --max=10 ``` - targets为unknown 的原因 ![image-20220314130425072](http://oss.linuxtxc.com/images/image-20220314130425072.png) - 需要安装metrics-server - HPA对应的pod,需要设置request资源 ```yaml #使用命令行设置pod 资源限制 kubectl set resources deployment/nginx-deployment --limits=cpu=800m ``` - 再次查看: ![image-20220314135225796](http://oss.linuxtxc.com/images/image-20220314135225796.png) - 使用ab 命令访问测试 ![image-20220315110716103](http://oss.linuxtxc.com/images/image-20220315110716103.png) - 查看 HPA状态 ![image-20220315110747229](http://oss.linuxtxc.com/images/image-20220315110747229.png) ##### 5.3.DaemonSet - DaemonSet类型的控制器可以保证集群中的每一台(或指定)节点上都运行一个副本,一般适用于日志收集、节点监控等场景 - DaemonSet控制器的特点: - 每向集群中添加一个节点的时候,指定的Pod副本也将添加到该节点上。 - 当节点从集群中移除的时候,Pod也会被垃圾回收。 - DaemonSet的资源清单: ```yaml apiVersion: apps/v1 # 版本号 kind: DaemonSet # 类型 metadata: # 元数据 name: # 名称 namespace: #命名空间 labels: #标签 controller: daemonset spec: # 详情描述 revisionHistoryLimit: 3 # 保留历史版本 updateStrategy: # 更新策略 type: RollingUpdate # 滚动更新策略 rollingUpdate: # 滚动更新 maxSurge: 30% #最大额外可以存在的副本数,可以为百分比,也可以为整数; 默认25% maxUnavailable: 1 # 最大不可用状态的Pod的最大值,可用为百分比,也可以为整数,默认25% selector: # 选择器,通过它指定该控制器管理那些Pod matchLabels: # Labels匹配规则 app: nginx-pod matchExpressions: # Expressions匹配规则 - key: app operator: In values: - nginx-pod template: # 模板,当副本数量不足时,会根据下面的模板创建Pod模板 metadata: labels: app: nginx-pod spec: containers: - name: nginx image: nginx:1.17.1 ports: - containerPort: 80 ``` - 案例 ```yaml apiVersion: apps/v1 kind: DaemonSet metadata: name: node-exporter namespace: kube-system labels: k8s-app: node-exporter spec: selector: matchLabels: app: node-exporter template: metadata: labels: app: node-exporter spec: containers: - image: prom/node-exporter name: node-exporter ports: - containerPort: 9100 protocol: TCP name: http ``` ##### 5.4.Job - Job主要用于负责批量处理短暂的一次性任务。J可以保证指定数量的Pod执行完成。 - Job的特点: - 当Job创建的Pod执行成功结束时,Job将记录成功结束的Pod数量。 - 当成功结束的Pod达到指定的数量时,Job将完成执行。 - Job的资源清单: ```yaml apiVersion: batch/v1 # 版本号 kind: Job # 类型 metadata: # 元数据 name: # 名称 namespace: #命名空间 labels: # 标签 controller: job spec: # 详情描述 completions: 1 # 指定Job需要成功运行Pod的总次数,默认为1 parallelism: 1 # 指定Job在任一时刻应该并发运行Pod的数量,默认为1 activeDeadlineSeconds: 30 # 指定Job可以运行的时间期限,超过时间还没结束,系统将会尝试进行终止 backoffLimit: 6 # 指定Job失败后进行重试的次数,默认为6 manualSelector: true # 是否可以使用selector选择器选择Pod,默认为false selector: # 选择器,通过它指定该控制器管理那些Pod matchLabels: # Labels匹配规则 app: counter-pod matchExpressions: # Expressions匹配规则 - key: app operator: In values: - counter-pod template: # 模板,当副本数量不足时,会根据下面的模板创建Pod模板 metadata: labels: app: counter-pod spec: restartPolicy: Never # 重启策略只能设置为Never或OnFailure containers: - name: counter image: busybox:1.30 command: ["/bin/sh","-c","for i in 9 8 7 6 5 4 3 2 1;do echo $i;sleep 20;done"] ``` - Job案例 ```yaml apiVersion: batch/v1 # 版本号 kind: Job # 类型 metadata: # 元数据 name: pc-job # 名称 namespace: dev #命名空间 spec: # 详情描述 manualSelector: true # 是否可以使用selector选择器选择Pod,默认为false parallelism: 1 ##指定job需要成功允许pods的次数。默认值:1 completions: 1 #指定job 在任一时刻应该并发运行pod 的数量。默认值:1 selector: # 选择器,通过它指定该控制器管理那些Pod matchLabels: # Labels匹配规则 app: counter-pod template: # 模板,当副本数量不足时,会根据下面的模板创建Pod模板 metadata: labels: app: counter-pod spec: restartPolicy: Never # 重启策略只能设置为Never或OnFailure containers: - name: counter image: busybox:1.30 command: [ "/bin/sh","-c","for i in 9 8 7 6 5 4 3 2 1;do echo $i;sleep 3;done" ] ``` ```shell #查看job运行情况 kubectl get job -n dev -w ``` ##### 5.5.CronJob(CJ) - CronJob控制器以Job控制器为其管控对象,并借助它管理Pod资源对象,Job控制器定义的作业任务在其控制器资源创建之后便会立即执行,但CronJob可以以类似Linux操作系统的周期性任务作业计划的方式控制器运行时间点及重复运行的方式,换言之,CronJob可以在特定的时间点反复去执行Job任务。 - 应用场景 - 数据备份 - 清理日志 - CronJob的资源清单: ```yaml apiVersion: batch/v1beta1 # 版本号 kind: CronJob # 类型 metadata: # 元数据 name: # 名称 namespace: #命名空间 labels: controller: cronjob spec: # 详情描述 schedule: #cron格式的作业调度运行时间点,用于控制任务任务时间执行 concurrencyPolicy: #并发执行策略 failedJobsHistoryLimit: #为失败的任务执行保留的历史记录数,默认为1 successfulJobsHistoryLimit: #为成功的任务执行保留的历史记录数,默认为3 jobTemplate: #job控制器模板,用于为cronjob控制器生成job对象,下面其实就是job的定义 metadata: {} spec: completions: 1 #指定Job需要成功运行Pod的总次数,默认为1 parallelism: 1 #指定Job在任一时刻应该并发运行Pod的数量,默认为1 activeDeadlineSeconds: 30 #指定Job可以运行的时间期限,超过时间还没结束,系统将会尝试进行终止 backoffLimit: 6 #指定Job失败后进行重试的次数,默认为6 template: #模板,当副本数量不足时,会根据下面的模板创建Pod模板 spec: restartPolicy: Never #重启策略只能设置为Never或OnFailure containers: - name: counter image: busybox:1.30 command: [ "/bin/sh","-c","for i in 9 8 7 6 5 4 3 2 1;do echo $i;sleep 20;done" ] ``` - schedule:cron表达式,用于指定任务的执行时间。 - */1 * * * *:表示分 时 日 月 周。 - 分钟的值从0到59。 - 小时的值从0到23。 - 日的值从1到31。 - 月的值从1到12。 - 星期的值从0到6,0表示星期日。 - 多个时间可以用逗号隔开,范围可以用连字符给出:* 可以作为通配符,/表示每... - concurrencyPolicy:并发执行策略 - Allow:运行Job并发运行(默认)。 - Forbid:禁止并发运行,如果上一次运行尚未完成,则跳过下一次运行。 - Replace:替换,取消当前正在运行的作业并使用新作业替换它。 - 案例 ```yaml apiVersion: batch/v1beta1 kind: CronJob metadata: name: pc-cronjob namespace: dev labels: controller: cronjob spec: schedule: "*/1 * * * *" jobTemplate: metadata: spec: template: spec: restartPolicy: OnFailure containers: - name: timing image: busybox:latest command: ["echo","hello k8s cronjob!"] ``` ```shell #查看cronjob 任务pod kubectl get pod -n dev ``` ![image-20220316104124649](http://oss.linuxtxc.com/images/image-20220316104124649.png) ##### 5.6.StatefulSet(有状态服务) - 无状态应用: - 认为Pod都是一样的。 - 没有顺序要求。 - 不用考虑在哪个Node节点上运行。 - 随意进行伸缩和扩展。 - 有状态应用: - 有顺序的要求。 - 认为每个Pod都是不一样的。 - pod有序的部署,扩容,删除和停止 - pod分配有个稳定的且唯一的网络标识 - pod分配有个独享的存储 - StatefulSet是Kubernetes提供的管理有状态应用的负载管理控制器。 - StatefulSet部署需要HeadLinessService(无头服务)。 为什么需要HeadLinessService(无头服务)? - 在用Deployment时,每一个Pod名称是没有顺序的,是随机字符串,因此是Pod名称是无序的,但是在StatefulSet中要求必须是有序 ,每一个Pod不能被随意取代,Pod重建后pod名称还是一样的。 - 而Pod IP是变化的,所以是以Pod名称来识别。Pod名称是Pod唯一性的标识符,必须持久稳定有效。这时候要用到无头服务,它可以给每个Pod一个唯一的名称 。 - StatefulSet常用来部署RabbitMQ集群、Zookeeper集群、MySQL集群、Eureka集群等。 - 案例模板 ```yaml apiVersion: v1 kind: Service metadata: name: service-headliness namespace: dev spec: selector: app: nginx-pod clusterIP: None # 将clusterIP设置为None,即可创建headliness Service type: ClusterIP ports: - port: 80 # Service的端口 targetPort: 80 # Pod的端口 --- apiVersion: apps/v1 kind: StatefulSet metadata: name: pc-statefulset namespace: dev spec: replicas: 3 serviceName: service-headliness selector: matchLabels: app: nginx-pod template: metadata: labels: app: nginx-pod spec: containers: - name: nginx image: nginx:1.17.1 ports: - containerPort: 80 ``` - Deployment和StatefulSet的区别:Deployment没有唯一标识而StatefulSet有唯一标识。 - StatefulSet的唯一标识是根据主机名+一定规则生成的。 - StatefulSet的唯一标识是`statefulset名称-编号(主机名).headless Service名称.命名空间.svc.cluster.local`。 - pod独享存储:statefulset的存储卷使用volumeClaimTemplate 创建,称为卷申请模板,当VolumeClaimTemplate 创建 一个PersistentVolume时,同时也会为每个pod分配并创建一个编号的PVC,每个PVC绑定 ###### 5.6.1.StatefulSet的金丝雀发布 - StatefulSet支持两种更新策略:OnDelete和RollingUpdate(默认),其中OnDelete表示删除之后才更新,RollingUpdate表示滚动更新 ```yaml apiVersion: v1 kind: Service metadata: name: service-headliness namespace: dev spec: selector: app: nginx-pod clusterIP: None # 将clusterIP设置为None,即可创建headliness Service type: ClusterIP ports: - port: 80 # Service的端口 targetPort: 80 # Pod的端口 --- apiVersion: apps/v1 kind: StatefulSet metadata: name: pc-statefulset namespace: dev spec: replicas: 3 type: RollingUpdate updateStrategy: rollingUpdate: partition: 2 #表示从第2个分区开始更新,默认是0 serviceName: service-headliness #headliness Service名称 selector: matchLabels: app: nginx-pod template: metadata: labels: app: nginx-pod spec: containers: - name: nginx image: nginx:1.17.1 ports: - containerPort: 80 ``` ---- #### 6.k8s 的service服务 - 在kubernetes中,Pod是应用程序的载体,我们可以通过Pod的IP来访问应用程序,但是Pod的IP地址不是固定的,这就意味着不方便直接采用Pod的IP对服务进行访问。 - 为了解决这个问题,kubernetes提供了为一组pod提供负载均衡,并且提供一个统一的入口地址,通过访问Service的入口地址就能访问到后面的Pod服务。 - Service在很多情况下只是一个概念,真正起作用的其实是kube-proxy服务进程,每个Node节点上都运行了一个kube-proxy的服务进程。当创建Service的时候会通过API Server向etcd写入创建的Service的信息,而kube-proxy会基于监听的机制发现这种Service的变化,然后它会将最新的Service信息转换为对应的访问规则。 ```shell # 10.97.97.97:80 是service提供的访问入口 # 当访问这个入口的时候,可以发现后面有三个pod的服务在等待调用, # kube-proxy会基于rr(轮询)的策略,将请求分发到其中一个pod上去 # 这个规则会同时在集群内的所有节点上都生成,所以在任何一个节点上访问都可以。 [root@k8s-node1 ~]# ipvsadm -Ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags  -> RemoteAddress:Port Forward Weight ActiveConn InActConn  TCP 10.97.97.97:80 rr   -> 10.244.1.39:80   Masq 1 0 0   -> 10.244.1.40:80   Masq 1 0 0   -> 10.244.2.33:80 Masq 1 0 0 ``` - kube-proxy支持的两种工作模式: - iptables模式: - iptables模式下,kube-proxy为Service后端的每个Pod创建对应的iptables规则,直接将发向Cluster IP的请求重定向到一个Pod的IP上。 - 该模式下kube-proxy不承担四层负载均衡器的角色,只负责创建iptables规则。该模式的优点在于较userspace模式效率更高,但是不能提供灵活的LB策略,当后端Pod不可用的时候无法进行重试。 - ipvs模式: - ipvs模式和iptables类似,kube-proxy监控Pod的变化并创建相应的ipvs规则。ipvs相对iptables转发效率更高,除此之外,ipvs支持更多的LB算法。 - 开启ipvs(必须安装ipvs内核模块,否则会降级为iptables): ```shell kubectl edit cm kube-proxy -n kube-system ``` ![编辑kube-proxy.gif](http://cdn.nlark.com/yuque/0/2021/gif/513185/1609904265505-1136f319-e955-4b3a-a5a0-fa830b8f3630.gif) ```shell #重新构建所有节点的kube-proxy pod kubectl delete pod -l k8s-app=kube-proxy -n kube-system ##查看ipvs模块是否开启成功 ipvsadm -Ln ##二进制安装修改ipvs模式(配置文件路径根据实际安装目录为准) # vi kube-proxy-config.yml mode: ipvs ipvs: scheduler: "rr" #重启kube-proxy服务 systemctl restart kube-proxy ``` ##### 6.1. Service类型 - Service的资源清单: ```yaml apiVersion: v1 # 版本 kind: Service # 类型 metadata: # 元数据 name: # 资源名称 namespace: # 命名空间 spec: selector: # 标签选择器,用于确定当前Service代理那些Pod app: nginx type: NodePort # Service的类型,指定Service的访问方式 clusterIP: #虚拟服务的IP地址,不写会默认生成 sessionAffinity: # session亲和性,支持ClientIP、None两个选项,默认值为None,ClientIP,即来自同一个客户端发起的所有请求都会转发到固定的一个Pod上 ports: # 端口信息 - port: 8080 # Service端口 protocol: TCP # 协议 targetPort : # Pod端口 nodePort: # 主机端口 ``` ###### 6.1.1.Endpoint - service关联pod一种资源 - Endpoint是kubernetes中的一个资源对象,存储在etcd中,用来记录一个service对应的所有Pod的访问地址,它是根据service配置文件中的selector描述产生的。 - 一个service由一组Pod组成,这些Pod通过Endpoints暴露出来,Endpoints是实现实际服务的端点集合。换言之,service和Pod之间的联系是通过Endpoints实现的。 ```shell #查看service 的详细信息 kubectl describe svc nginx-service -n app ``` ![image-20220320182429946](http://oss.linuxtxc.com/images/image-20220320182429946.png) - 查看endpoint ``` kubectl get endpoints -n web ``` ![image-20220608151612784](http://oss.linuxtxc.com/images/image-20220608151612784.png) spec.type的说明: - ClusterIP:默认值,它是kubernetes系统自动分配的虚拟IP,只能在集群内部访问。 - NodePort:将Service通过指定的Node上的端口暴露给外部,通过此方法,就可以在集群外部访问服务。 - LoadBalancer:使用外接负载均衡器完成到服务的负载分发,注意此模式需要外部云环境的支持。 - ExternalName:把集群外部的服务引入集群内部,直接使用。 ###### 6.1.2.ClusterIP - 只允许集群内部访问 ```yaml apiVersion: v1 kind: Service metadata: name: nginx-service namespace: app spec: selector: # 标签选择器,用于确定当前Service代理那些Pod app: nginx clusterIP: 10.0.0.133 # service的IP地址,如果不写,默认会生成一个 type: ClusterIP ports: # - port: 80 # Service端口 protocol: TCP targetPort : 80 ``` ###### 6.1.3.HeadLiness - 这类Service不会分配Cluster IP,如果想要访问Service,只能通过Service的域名进行查询。 - 创建service-headliness.yaml文件,内容如下: ```yaml apiVersion: v1 kind: Service metadata: name: service-headliness namespace: dev spec: selector: app: nginx-pod clusterIP: None # 将clusterIP设置为None,即可创建headliness Service type: ClusterIP ports: - name: http port: 80 # Service的端口 targetPort: 80 # Pod的端口 ports: - name: https port: 443 # Service的端口 targetPort: 443 # Pod的端口 ``` ###### 6.2.4.NodePort - NodePort的工作原理就是将Service的端口映射到Node的一个端口上,然后就可以通过`NodeIP:NodePort`来访问Service了。 - 创建service-nodeport.yaml文件,内容如下: ```yaml apiVersion: v1 kind: Service metadata: name: service-nodeport namespace: dev spec: selector: app: nginx-pod type: NodePort # Service类型为NodePort ports: - port: 80 # Service的端口 targetPort: 80 # Pod的端口 nodePort: 30002 # 指定绑定的node的端口(默认取值范围是30000~32767),如果不指定,会默认分配 ``` - 查看Service: ```yaml kubectl get svc service-nodeport -n dev -o wide ``` ###### 6.1.5.LoadBalancer - LoadBalancer和NodePort很相似,目的都是向外部暴露一个端口,区别在于LoadBalancer需要在集群的外部再配置一个负载均衡设备,外部服务发送到这个设备上的请求,会被设备负载之后转发到集群中。 - 创建service-LoadBalancer.yaml,内容如下 ```yaml apiVersion: v1 kind: Service metadata: name: service-nodeport namespace: web spec: selector: app: web-deployment type: LoadBalancer # Service类型为NodeBalancer ports: - port: 80 # Service的端口 targetPort: 80 # Pod的端口 ``` ###### 6.1.6. ExternalName - ExternalName类型的Service用于引入集群外部的服务,它通过externalName属性指定一个服务的地址,然后在集群内部访问此Service就可以访问到外部的服务了。 - 创建service-externalname.yaml文件,内容如下: ```yaml apiVersion: v1 kind: Service metadata: name: test-external namespace: app spec: type: ExternalName externalName: 192.168.2.214 ports: - name: http port: 80 protocol: TCP targetPort: 80 #目标端口 ``` ###### 6.1.7.k8s 接入外部数据库 - 集群内部访问外部数据库或者中间件一般采用endpoints与service关联方式映射。 - 创建endpoints-mysql.yaml文件,内容如下: ```yaml apiVersion: v1 kind: Endpoints metadata: name: mysql-214 namespace: app subsets: - addresses: - ip: 192.168.2.214 ports: - port: 16303 ``` - 创建 service-mysql.yaml文件,内容如下: ```yaml apiVersion: v1 kind: Service metadata: name: mysql-214 #要与endpoints 的名称一样 namespace: app spec: type: ClusterIP ports: - port: 16303 # Service端口 protocol: TCP targetPort : 16303 ``` ###### 6.1.8.部署案例 - 创建nginx-deployment.yaml 文件 ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment namespace: app spec: replicas: 1 strategy: #策略 type: RollingUpdate rollingUpdate: #滚动更新 maxSurge: 30% #最大额外可以存在的副本数,可以为百分比,也可以为整数; 默认25% maxUnavailable: 30% #最大不可用状态的 ;Pod 的最大值,可以为百分比,也可以为整数,默认25% selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.17.3 ports: - containerPort: 80 ``` - - 创建 nginx-service-nodeport.yaml ```yaml apiVersion: v1 kind: Service metadata: name: service-nodeport namespace: app spec: selector: app: nginx type: NodePort # Service类型为NodePort ports: - port: 80 # Service的端口 targetPort: 80 # Pod的端口 nodePort: 30082 # 指定绑定的node的端口(默认取值范围是30000~32767),如果不指定,会默认分配 ``` - 测试访问 ```yaml #查看service kubectl get svc service-nodeport -n app -o wide 或者 kubectl describe service service-nodeport -n app ``` ![image-20220324160508048](http://oss.linuxtxc.com/images/image-20220324160508048.png) ###### 6.1.9.pod使用主机网络 - 使用hostNetwork: true 参数 ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: nginx spec: replicas: 1 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: # 使用主机网络 hostNetwork: true # 该设置是使POD使用k8s的dns,dns配置在/etc/resolv.conf文件中 # 如果不加,pod默认使用所在宿主主机使用的DNS,这样会导致容器内不能通过service name访问k8s集群中其他POD dnsPolicy: ClusterFirstWithHostNet containers: - name: nginx image: nginx:1.17.9 ports: - name: metrics # 如果hostNetwork: true,hostPort必须跟containerPort一样,所以hostPort一般不写,端口也是占用宿主机上的端口。 hostPort: 80 containerPort: 80 ``` ##### 6.2.ingress 资源 - Service对集群之外暴露服务的主要方式有两种:NodePort和LoadBalancer,但是这两种方式,都有一定的缺点: - NodePort方式的缺点是会占用很多集群机器的端口,那么当集群服务变多的时候,这个缺点就愈发明显。 - LoadBalancer的缺点是每个Service都需要一个LB,浪费,麻烦,并且需要kubernetes之外的设备的支持。 - 基于这种现状,kubernetes提供了Ingress资源对象,Ingress只需要一个NodePort或者一个LB就可以满足暴露多个Service的需求。 ###### 6.2.1安装ingress需要的环境 ```shell #wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.1/deploy/static/provider/cloud/deploy.yaml #项目地址 #https://kubernetes.github.io/ingress-nginx/deploy #修改镜像地址 image: k8s.gcr.io/ingress-nginx/controller:v1.1.1@sha256:d8196e3bc1e72547c5dec66d6556c0ff92a23f6d0919b206be170bc90d5f9185 修改成: image: registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:v1.1.1 image: k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.1.1@sha256:64d8c73dca984af206adf9d6d7e46aa550362b1d7a01f3a0a91b20cc67868660 修改成: image: registry.cn-hangzhou.aliyuncs.com/google_containers/kube-webhook-certgen:v1.1.1 [root@k8s_master ~]# wget http://oss.linuxtxc.com/ingress-nginx.zip [root@k8s_master ~]# unzip ingress-nginx.zip [root@k8s_master ~]# kubectl apply -f deploy.yaml ``` ![image-20220611171810086](http://oss.linuxtxc.com/images/image-20220611171810086.png) ###### 6.2.2.Http代理 - 为服务创建 service,yaml文件内容如下: ```yaml apiVersion: v1 kind: Service metadata: name: nginx-service namespace: app spec: selector: # 标签选择器,用于确定当前Service代理那些Pod app: nginx type: ClusterIP ports: # - name: http port: 80 # Service端口 protocol: TCP targetPort : 80 - name: https port: 443 # Service端口 protocol: TCP targetPort : 443 --- apiVersion: v1 kind: Service metadata: name: tomcat-service namespace: app spec: selector: app: tomcat type: ClusterIP ports: - port: 8080 targetPort: 8080 ``` - 创建ingress-http.yaml文件,内容如下: ```yaml apiVersion: extensions/v1beta1 kind: Ingress metadata: name: ingress-http namespace: app spec: rules: - host: nginx.linuxtxc.com http: paths: - path: / backend: serviceName: nginx-service servicePort: 80 #service端口 - host: tomcat.linuxtxc.com http: paths: - path: / backend: serviceName: tomcat-service servicePort: 8080 ``` - kubernetes1.19版本之后 ingress配置yaml ```yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: web-ingress namespace: app spec: ingressClassName: nginx rules: - host: "nginx.linuxtxc.com" http: paths: - path: / pathType: Prefix backend: service: name: web-service port: number: 80 ``` - 查看ingress端口: ```shell kubectl get ing ingress-http -n app ``` ![image-20220411203539747](http://oss.linuxtxc.com/images/image-20220411203539747.png) ```shell #查看访问ingress端口 kubectl get service -n ingress-nginx ``` ![image-20220411203347463](http://oss.linuxtxc.com/images/image-20220411203347463.png) - 访问URL:http://tomcat.linuxtxc.com:32443(可以在本地hosts文件中添加解析访问) ![image-20220411203156937](http://oss.linuxtxc.com/images/image-20220411203156937.png) ###### 6.2.3.修改ingress访问端口 ```shell #查看ingress-controller 的pod部署在哪个节点上 kubectl get pod -n ingress-nginx -o wide ``` ![image-20220611164948163](http://oss.linuxtxc.com/images/image-20220611164948163.png) - 修改ingress配置,并将上面nginx.linuxtxc.com 域名指向node01 公网IP ```shell kubectl edit deployment.apps/ingress-nginx-controller -n ingress-nginx #添加 --http-port=83 ``` ![image-20220611171040476](http://oss.linuxtxc.com/images/image-20220611171040476.png) ```shell #删除旧的ingress-nginx-controller pod ,让其自动重新创建 kubectl delete pod ingress-nginx-controller-6bc4ff465c-pmjdr -n ingress-nginx ``` - 访问url:http://nginx.linuxtxc.com:83 ![image-20220611173000581](http://oss.linuxtxc.com/images/image-20220611173000581.png) ###### 6.2.4.Https代理 ```shell 为ingress 配置https: (1)openssl req -newkey rsa:4096 -nodes -sha256 -keyout /opt/k8s/https/linuxtxc.com.key -x509 -out /opt/k8s/https/linuxtxc.com.crt -subj /C=CN/ST=BJ/L=BJ/O=DEVOPS/CN=linuxtxc.com -days 3650 (2)kubectl create secret tls tls-linuxtxc.com --key=/opt/k8s/https/linuxtxc.com.key --cert=/opt/k8s/https/linuxtxc.com.crt -n app req    产生证书签发申请命令 -newkey 生成新私钥 rsa:4096 生成秘钥位数 -nodes 表示私钥不加密 -sha256 使用SHA-2哈希算法 -keyout 将新创建的私钥写入的文件名 -x509   签发X.509格式证书命令。X.509是最通用的一种签名证书格式。 -out 指定要写入的输出文件名 -subj 指定用户信息 -days 有效期 ``` - 创建ingress-https.yaml ```yaml apiVersion: extensions/v1beta1 kind: Ingress metadata: name: ingress-https namespace: app spec: tls: - hosts: - nginx.linuxtxc.com - tomcat.linxtxc.com secretName: tls-linuxtxc.com ## 指定秘钥 rules: - host: nginx.linuxtxc.com http: paths: - path: / backend: serviceName: nginx-service servicePort: 80 - host: tomcat.linuxtxc.com http: paths: - path: / backend: serviceName: tomcat-service servicePort: 8080 ``` - kubernetes1.19版本之后 ingress的yaml配置 ```yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: web-ingress spec: tls: - hosts: - nginx.linuxtxc.com secretName: tls-linuxtxc.com ## 指定秘钥 ingressClassName: nginx rules: - host: "nginx.linuxtxc.com" http: paths: - path: / pathType: Prefix backend: service: name: web-service port: number: 80 ``` - 查看ingress https访问端口 ```shell kubectl get service -n ingress-nginx ``` ![image-20220613195734911](http://oss.linuxtxc.com/images/image-20220613195734911.png) - 修改https 访问端口 ```shell kubectl edit deployment.apps/ingress-nginx-controller -n ingress-nginx ``` ![image-20220613200814699](http://oss.linuxtxc.com/images/image-20220613200814699.png) - 删除旧的ingress-controller 的pod,让其重新生成 ```shell kubectl delete pod ingress-nginx-controller-764766d96f-mtpmd -n ingress-nginx ``` - 重新使用修改的端口访问 ![image-20220613201241842](http://oss.linuxtxc.com/images/image-20220613201241842.png) ###### 6.2.5.ingress个性化配置 ```yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: web-ingress annotations: nginx.ingress.kubernetes.io/proxy-connect-timeout: 600s nginx.ingress.kubernetes.io/proxy-send-timeout: 600s nginx.ingress.kubernetes.io/proxy-read-timeout: 600s nginx.ingress.kubernetes.io/proxy-body-size: 8m #客户端请求正文的最大允许大小 nginx.ingress.kubernetes.io/proxy-buffering: "on" #打开代理缓冲 nginx.ingress.kubernetes.io/proxy-buffers-number: "4" #代理缓冲区数 nginx.ingress.kubernetes.io/proxy-buffer-size: "8k" #代理缓冲区大小 nginx.ingress.kubernetes.io/proxy-max-temp-file-size: "1024m" #代理最大临时文件大小 #nginx.ingress.kubernetes.io/proxy-http-version: "1.0" #代理http版本 #nginx.ingress.kubernetes.io/connection-proxy-header: "keep-alive" #连接代理的标头 #nginx.ingress.kubernetes.io/enable-access-log: "false" #启用访问日志 #nginx.ingress.kubernetes.io/enable-rewrite-log: "true" #启用日志重写 #nginx.ingress.kubernetes.io/x-forwarded-prefix: "/" #X-Forwarded-Prefix标头,匹配/之后对接下来的进行操作 #nginx.ingress.kubernetes.io/rewrite-target: https://www.baidu.com #重定向 #nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" #后端连接协议 #nginx.ingress.kubernetes.io/permanent-redirect: https://www.baidu.com #永久重定向(301) #nginx.ingress.kubernetes.io/whitelist-source-range: 220.167.31.8i #允许什么ip访问 nginx.ingress.kubernetes.io/configuration-snippet: | #自定义配置 if ($http_user_agent ~* '(iphone)') { rewrite ^/(.*) https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/annotations.md break; } spec: tls: - hosts: - nginx.linuxtxc.com secretName: tls-linuxtxc.com ## 指定秘钥 ingressClassName: nginx rules: - host: "nginx.linuxtxc.com" http: paths: - path: / pathType: Prefix backend: service: name: web-service port: number: 80 ``` ###### 6.2.6.ingress-nginx 高可用方案 - 通过DaemonSet+NodeSelector实现将副本在特定节点上运行,同时使用宿主机网络,可以在访问ingress时不需要加NodePort端口 ```shell #将ingress-controller yaml文件中的Deployment改为 DaemonSet,replicas注释掉,使用nodeSelector调度pod到指定的node上,还可以使用keepalived配置VIP,在负载均衡器上配置VIP地址 vim deploy.yaml #给节点打上标签 kubectl label node k8s-node01 ingress-nginx=true kubectl label node k8s-node02 ingress-nginx=true ``` - 测试直接使用域名访问 ##### 6.3.NetworkPolicy(网络策略) - 是一种关于 Pod 间及与其他网络端点间所允许的通信规则的规范。 ```yaml apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: test-network-policy namespace: default spec: #networkpolicy规约中包含了在一个命名空间中定义特定网络策略所需的所有信息 podSelector: #每个networkpolicy都包含一个podselector,对有其标签的pod(role:db),没有的话就对应所有命名空间下所有的pod matchLabels: role: db #标签 policyTypes: #每个networkpolicy都包含一个policytype列表,包含ingress和egress - Ingress #定义所选择的pod入站规则,如果此字段为空则不允许任何入站流量 - Egress #定义所选择的pod出战规则,如果此字段为空则不允许任何出站流量 ingress: - from: - ipBlock: #针对特定的ip cidr范围设置策略,如果设置此字段,则不可以设置其他字段 cidr: 172.17.0.0/16 #cidr是ip范围,允许这个范围内的ip访问networkpolicy的podselector匹配的pod集合 except: #except是ip范围,不允许这个范围内的ip访问networkpolicy的podselector匹配的pod集合 - 172.17.1.0/24 - namespaceSelector: #这将选择特定的命名空间,应将所有的pod用做输入源或者输出目的地 matchLabels: project: myproject - podSelector: #这将与在networkpolicy相同的命名空间中选择带有特定标签的pod(role:frontend),应将其允许作为入口源或者出口目的地 matchLabels: role: frontend ports: - protocol: TCP port: 6379 egress: - to: - ipBlock: cidr: 10.0.0.0/24 ports: - protocol: TCP port: 5978 ```