kubernetes完整学习笔记


markdown文档笔记下载地址:https://install-data.oss-cn-hongkong.aliyuncs.com/%E7%AC%94%E8%AE%B0/kubernetes%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.md

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.环境准备
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
ip_vs_wrr              12697  0 
ip_vs_rr               12600  0 
ip_vs_sh               12688  0 
ip_vs                 145497  6 ip_vs_rr,ip_vs_sh,ip_vs_wrr
nf_conntrack          133095  9 ip_vs,nf_nat,nf_nat_ipv4,nf_nat_ipv6,xt_conntrack,nf_nat_masquerade_ipv4,nf_conntrack_netlink,nf_conntrack_ipv4,nf_conntrack_ipv6
libcrc32c              12644  4 xfs,ip_vs,nf_nat,nf_conntrack



[root@master ipvs]# echo "bash /opt/ipvs/ipvs.sh" >>/etc/rc.local
[root@master ipvs]# chmod +x /etc/rc.local
1.2.安装docker(每台都执行)
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

1.3.安装kubeadm和kubelet(每台都执行)
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.19.0-0.x86_64  kubeadm-1.19.0-0.x86_64 kubectl-1.19.0-0.x86_64

systemctl enable kubelet
1.4.使用kubeadm部署master
kubeadm init --kubernetes-version=1.19.0 --apiserver-advertise-address=172.16.8.124  --service-cidr=10.64.0.0/24 --pod-network-cidr=10.244.0.0/16   (master上执行,--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加入集群
#当主节点启动完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

#查看组件健康情况
kubectl get  cs

kubernetes完整学习笔记_第1张图片

  • 解决方法
vim  /etc/kubernetes/manifests/kube-controller-manager.yaml (注释掉 - --port=0vim  /etc/kubernetes/manifests/kube-scheduler.yaml          (注释掉 - --port=0)
systemctl start kubelet 

#再次查看

kubernetes完整学习笔记_第2张图片

  • 过会儿节点也都正常了

kubernetes完整学习笔记_第3张图片

1.7.安装pod网络插件
#主节点执行
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/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://docs.projectcalico.org/manifests/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
#安装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

# 安装Compose命令补全工具
curl -L https://raw.githubusercontent.com/docker/compose/$(docker-compose version --short)/contrib/completion/bash/docker-compose -o /etc/bash_completion.d/docker-compose

#重启docker
systemctl daemon-reload
systemctl restart docker

#安装harbor
wget https://storage.googleapis.com/harbor-releases/release-1.8.0/harbor-offline-installer-v1.8.0.tgz
tar xvf harbor-offline-installer-v1.8.0.tgz
cd harbor/
vim harbor.yml (修改默认端口)
./prepare
./install.sh

#登录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)
1.9.安装coredns
#官方模板: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集群
(master,node都执行)
kubeadm  reset 
rm -rf /etc/cni/net.d

(master上执行 )
kubeadm init --kubernetes-version=1.19.0 --apiserver-advertise-address=192.168.3.124  --service-cidr=10.64.0.0/24 --pod-network-cidr=10.244.0.0/16
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
vim  /etc/kubernetes/manifests/kube-controller-manager.yaml (注释掉 - --port=0vim  /etc/kubernetes/manifests/kube-scheduler.yaml          (注释掉 - --port=0)
systemctl start kubelet 

(node 上执行)
kubeadm reset
kubeadm join 192.168.3.124:6443 --token f62e1g.exfdrr8bg2fxpdmu \
    --discovery-token-ca-cert-hash sha256:7e4762cccce2e8306b6635cbc2091eae34bbf33577276413521a343c49fc026a
1.11.切换容器引擎为Containerd
#启动模块(默认已经启用)
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镜像配置加速地址设置为阿里云镜像仓库地址

vi /etc/containerd/config.toml
   [plugins."io.containerd.grpc.v1.cri"]
      sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.2"  
         ...
         [plugins."io.containerd.grpc.v1.cri".containerd.default_runtime.options]
            SystemdCgroup = true
             ...
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
          endpoint = ["https://b9pmyelo.mirror.aliyuncs.com"]

#重启containerd
systemctl restart containerd
  • 配置kubelet使用containerd
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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mLgnwFu3-1654139062211)(C:\Users\linux\AppData\Roaming\Typora\typora-user-images\image-20220531181711832.png)]

  • 管理容器工具

containerd提供了ctr命令行工具管理容器,但功能比较简单,所以一般会用crictl工具检查和调试容器。

项目地址:https://github.com/kubernetes-sigs/cri-tools/

设置crictl连接containerd:

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

2.kubernetes 资源管理

2.1.kubectl create
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模板
kubectl create deployment  deploy-nginx  --image=nginx:1.17.2 --replicas=3  -n dev --dry-run=client -o yaml > deploy-nginx.yaml
2.2.kubectl api-resources
kubectl api-resources   #查看k8s所有的资源以及对应的apiversion

kubectl api-versions    #查看k8s所有 版本号
2.3.kubectl explain
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(每周)。

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
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
#进入pod容器中
kubectl exec -it  nginx-deployment-798444d598-87hlk  -n web /bin/sh
2.7.kubectl get
kubectl get cs   #获取集群健康状态

kubectl get csr  #查看申请加入kubernetes集群的token信息

kubectl get endpoints  #获取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
kubectl edit cm kubeadm-config -n kube-system   #cm,configMap;编辑configMap中的配置
2.9.kubectl logs
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 的合并日志
2.10.kubectl delete
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
kubectl autoscale deployment deployment-nginx --cpu-percent=60 --min=2 --max=10     #使用 Deployment “deployment-nginx”设定,使用默认的自动伸缩策略,指定目标CPU使用率,使其Pod数量在2到10之间。
2.12.kubectl patch
#使用(patch)补丁修改、更新资源的字段。
kubectl patch pod rc-nginx-2-kpiqt -p '{"metadata":{"labels":{"app":"nginx-3"}}}'  #修改资源配置
2.13.kubectl replace
kubectl replace -f rc-nginx.yaml   #根据yaml文件更新修改后配置资源,会停掉原来的资源,重新创建
2.14.kubectl scale
kubectl scale rc redis --replicas=3 -n web    #操作pod 的扩容和缩容

kubectl scale --replicas=2 -f redis-slave-deployment.yaml   
2.15.kubectl rollout
status:显示当前升级状态
history:显示升级历史记录
pause:暂停版本升级过程
resume:继续已经暂停的版本升级过程
restart:重启版本升级过程
undo:回滚到上一级版本 (可以使用--to-revision,指定版本)
kubectl apply -f pc-deployment.yml --record  (--record,记录操作记录,便于回滚)

#查看历史版本
kubectl  rollout history deployment -n app    

更新镜像:
(1)通过kubectl set 命令去更改
kubectl set image  deploy  nginx-deployment nginx=nginx:1.15.2 -n app   && 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

#版本回滚到v1
kubectl rollout undo deploy nginx-deployment --to-revision=1 -n app
2.16.kubectl taint
 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
kubectl run nginx --image=nginx:1.17.1 -n web   #命令使用镜像创建容器
2.18.kubectl apply
#如果资源不存在,就创建,相当于kubectl create。
#如果资源存在,就更新,相当于kubectl patch。
kubectl apply -f nginx-pod.yaml -n web --record  (--record,记录操作记录,便于回滚)
2.19.kubectl top
kubectl top  pod/node  -n dev   #查看资源使用情况(需要安装metrics-server)
2.20.kubectl expose
#将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
#将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


3.kubernetes 的Pod 详解

pod:k8s 最小控制单元,其中包含一个pause容器(根容器),多个user 容器,提供服务,pod中容器共享网络,存储资源
pause容器作用:可以根据它判断pod的健康状态,同时在pause容器上设置IP,可以让同一个pod中的所有容器共用

3.1.Pod 所有参数配置
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: > #设置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.2.Pod资源限制
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命令:在容器内执行一次命令。
……
  lifecycle:
     postStart: 
        exec:
           command:
             - cat
             - /tmp/healthy
……

​ ② tcpSocket:在当前容器尝试访问指定的socket。

…… 
   lifecycle:
      postStart:
         tcpSocket:
            port: 8080
……

​ ③ httpGet:在当前容器中向某url发起HTTP请求。

…… 
   lifecycle:
      postStart:
         httpGet:
            path: / #URI地址
            port: 80 #端口号
            host: 192.168.109.100 #主机地址  
            scheme: HTTP #支持的协议,http或者https
……

以exec方式为例,演示下钩子函数的使用,创建pod-hook-exec.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不会转发流量。
  • 上面两种探针目前均支持三种探测方式:

    • ① exec命令:在容器内执行一次命令,如果命令执行的退出码为0,则认为程序正常,否则不正常。
----------------------------
readinessProbe:
      exec:
        command:
        - cat
        - /etc/hosts
      initialDelaySeconds: 5
      timeoutSeconds: 2
      successThreshold: 3
      failureThreshold: 2
      periodSeconds: 5
-----------------------------
    • ② tcpSocket:将会尝试访问一个用户容器的端口,如果能够建立这条连接,则认为程序正常,否则不正常。
……
   livenessProbe:
     tcpSocket:
       port: 8080
     failureThreshold: 5           #检测失败5次表示未就绪
     initialDelaySeconds: 60       #初始化时间
     periodSeconds: 10             #检测间隔
     successThreshold: 1           #检查成功为2次表示就绪
     timeoutSeconds: 5             #检测失败1次表示未就绪 
……
    • ③ httpGet:调用容器内web应用的URL,如果返回的状态码在200和399之前,则认为程序正常,否则不正常。
------------------------ 
 livenessProbe:         #健康检查方式:[readinessProbe,livenessProbe,StartupProbe]
   httpGet:                      #请求方式
     path: /health               #请求路径
     port: 8080                  #请求端口
     scheme: HTTP                ##请求协议
   failureThreshold: 5           #检测失败5次表示未就绪
   initialDelaySeconds: 60       #初始化时间
   periodSeconds: 10             #检测间隔
   successThreshold: 1           #检查成功为2次表示就绪
   timeoutSeconds: 5             #检测失败1次表示未就绪
----------------------------
  • startupProbe : 启动探测,k8s1.16版本后新加的探测方式,用于判断容器内应用程序是否已经启动,如果配置了startuprobe,就会先禁用其他的探测,直到它成功为止。
----------------------------------
startupProbe:             #健康检查方式:[readinessProbe,livenessProbe,StartupProbe]
  httpGet:                        #请求方式
    path: /                       #请求路径
    port: 8080                    #请求端口
    scheme: HTTP                  #请求协议
  failureThreshold: 3             #检测失败3次表示未就绪
  periodSeconds: 10               #检测间隔
  successThreshold: 1             #检查成功为2次表示就绪
  timeoutSeconds: 1               #检测失败1次表示未就绪
----------------------------------

initialDelaySeconds # 容器启动后等待多少秒执行第一次探测。

timeoutSeconds # 探测超时时间。默认1秒,最小1秒。

periodSeconds # 执行探测的频率。默认是10秒,最小1秒。

failureThreshold # 连续探测失败多少次才被认定为失败。默认是3。最小值是1。

successThreshold # 连续探测成功多少次才被认定为成功。默认是1。

重启策略:

    • Always:容器失效时,自动重启该容器,默认值。
    • OnFailure:容器终止运行且退出码不为0时重启。
    • Never:不论状态如何,都不重启该容器。
  • startupprobe+readinessProbe+ livenessProbe混合案例

apiVersion: v1                # 必选,API的版本号
kind: Pod                     # 必选,类型Pod
metadata:                     # 必选,元数据
  name: read-startup          # 必选,符合RFC 1035规范的Pod名称
  labels:                     # 可选,标签选择器,一般用于过滤和区分Pod
    app: nginx
    role: frontend             # 可以写多个
  annotations:                 # 可选,注释列表,可以写多个
    app: nginx
spec:                           # 必选,用于定义容器的详细信息
  containers:                   # 必选,容器列表
  - name: read-startup          # 必选,符合规范的容器名称
    image: nginx:latest         # 必选,容器所用的镜像
    imagePullPolicy: Always     # 可选,镜像拉取策略
    command: # 可选,容器启动执行的命令
    - nginx
    - -g
    - "daemon off;"
    workingDir: /usr/share/nginx/html       # 可选,容器的工作目录
    ports:                     # 可选,容器需要暴露的端口号列表
    - name: http               # 端口名称
      containerPort: 80        # 端口号
      protocol: TCP            # 端口协议,默认TCP
    env:                       # 可选,环境变量配置列表
    - name: TZ                 # 变量名
      value: Asia/Shanghai     # 变量的值
    - name: LANG
      value: en_US.utf8
    readinessProbe:
      exec:
        command:
        - cat
        - /etc/hosts
      initialDelaySeconds: 5
      timeoutSeconds: 2
      successThreshold: 3
      failureThreshold: 2
      periodSeconds: 5
    startupProbe:
      httpGet:
        path: /
        port: 80
      failureThreshold: 30
      periodSeconds: 10
    livenessProbe:
      httpGet:
        path: /healthz
        port: 80
      failureThreshold: 1
      periodSeconds: 10
    restartPolicy: Never   #重启策略  

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文件,内容如下:
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调度到目标节点,该匹配规则是强制约束。

#给node节点添加标签
kubectl label node k8s-node1 node=web
kubectl label node k8s-node2 node=app
  • 创建pod-nodeselector.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的可选配置项:
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文件,内容如下:
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文件,内容如下:
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的可选配置项:
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文件,内容如下:
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文件,内容如下:
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不在一个区域的功能。
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驱逐。
#设置污点
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 节点名称

#给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通过容忍忽略拒绝

  • 容忍的详细配置:
kubectl explain  pod.spec.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:

  • 容忍一切污点(慎用):

tolerations: # 容忍
  - key: "tag" # 要容忍的污点的key
    operator: Exists # 操作符
    effect: NoExecute # 添加容忍的规则,这里必须和标记的污点规则相同  
tolerations: # 容忍
  - key: "tag" # 要容忍的污点的key
    operator: Exists # 操作符
tolerations: # 容忍
  - operator: Exists # 操作符
  • 创建pod-toleration.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 # 添加容忍的规则,这里必须和标记的污点规则相同
  • 案例:
#给两个节点都打上污点
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下添加更新策略

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
  • 镜像更新
(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

kubernetes完整学习笔记_第4张图片

  • 查看rs,发现原来的rs依旧存在,只是Pod的数量变为0,而后又产生了一个rs,Pod的数量变为3
kubectl get rs -n app

kubernetes完整学习笔记_第5张图片

  • 查看历史版本
kubectl  rollout history deployment -n app 

image-20220312152424542

  • 版本回滚
kubectl rollout undo deploy nginx-deployment --to-revision=1 -n app
  • 金丝雀发布(在一批新的Pod资源创建完成后立即暂停更新过程)
(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(用来收集集群中的资源使用情况。)
#wget https://github.com/kubernetes-sigs/metrics-server/archive/v0.3.6.tar.gz
wget  https://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

kubernetes完整学习笔记_第6张图片

  • 安装安装metrics-server(v0.4.1)
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

kubernetes完整学习笔记_第7张图片

  • 查看metrics-server生成的Pod:
kubectl get pod -n kube-system

kubernetes完整学习笔记_第8张图片

5.2.2.错误排查
  • 查看资源使用情况报错

image-20220312165514330

  • 排查错误
systemctl status kube-apiserver -l  #或者 journalctl -u kube-apiserver

image-20220312173924651

  • metric-server安装要满足2个条件

    • 在master节点要能访问metrics server pod ip(kubeadm部署默认已经满足该条件,二进制部署需注意要在master节点也部署node组件)

    • apiserver启用聚合层支持(kubeadm默认已经启用,二进制部署需自己启用)

因为我是二进制安装的,所以在master上安装node组件就可以了

kubectl top pod -n app

kubernetes完整学习笔记_第9张图片

5.2.3.部署HPA案例
  • 使用之前创建的nginx-deployment,使用kubectl edit 将副本数改为 1

kubernetes完整学习笔记_第10张图片

  • 创建 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
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
#使用命令创建HPA控制器
kubectl autoscale deployment nginx-hpa --cpu-percent=3 --min=1 --max=10
  • targets为unknown 的原因

image-20220314130425072

  • 需要安装metrics-server

  • HPA对应的pod,需要设置request资源

#使用命令行设置pod 资源限制
kubectl set resources deployment/nginx-deployment --limits=cpu=800m
  • 再次查看:

kubernetes完整学习笔记_第11张图片

  • 使用ab 命令访问测试

kubernetes完整学习笔记_第12张图片

  • 查看 HPA状态

kubernetes完整学习笔记_第13张图片

5.3.DaemonSet
  • DaemonSet类型的控制器可以保证集群中的每一台(或指定)节点上都运行一个副本,一般适用于日志收集、节点监控等场景

  • DaemonSet控制器的特点:

    • 每向集群中添加一个节点的时候,指定的Pod副本也将添加到该节点上。
    • 当节点从集群中移除的时候,Pod也会被垃圾回收。
  • DaemonSet的资源清单:

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
  • 案例
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的资源清单:

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案例
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" ]
#查看job运行情况
kubectl get job -n dev -w
5.5.CronJob(CJ)
  • CronJob控制器以Job控制器为其管控对象,并借助它管理Pod资源对象,Job控制器定义的作业任务在其控制器资源创建之后便会立即执行,但CronJob可以以类似Linux操作系统的周期性任务作业计划的方式控制器运行时间点及重复运行的方式,换言之,CronJob可以在特定的时间点反复去执行Job任务。

  • CronJob的资源清单:

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:替换,取消当前正在运行的作业并使用新作业替换它。
  • 案例

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!"]
#查看cronjob 任务pod
kubectl get pod -n dev

image-20220316104124649

5.6.StatefulSet(有状态服务)
  • 无状态应用:

    • 认为Pod都是一样的。
    • 没有顺序要求。
    • 不用考虑在哪个Node节点上运行。
    • 随意进行伸缩和扩展。
  • 有状态应用:

    • 有顺序的要求。
    • 认为每个Pod都是不一样的。
    • 需要考虑在哪个Node节点上运行。
    • 需要按照顺序进行伸缩和扩展。
    • 让每个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集群等。

  • 案例模板

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的唯一标识是主机名.headless Service名称.命名空间.svc.cluster.local

5.6.1.StatefulSet的金丝雀发布
  • StatefulSet支持两种更新策略:OnDelete和RollingUpdate(默认),其中OnDelete表示删除之后才更新,RollingUpdate表示滚动更新
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信息转换为对应的访问规则。

# 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):

kubectl edit cm kube-proxy -n kube-system

kubernetes完整学习笔记_第14张图片

#删除原来的kube-proxy pod
kubectl delete pod -l k8s-app=kube-proxy -n kube-system

##测试ipvs模块是否开启成功
ipvsadm -Ln
6.1. Service类型
  • Service的资源清单:
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实现的。

#查看service 的详细信息
kubectl describe svc nginx-service -n app

kubernetes完整学习笔记_第15张图片

spec.type的说明:

  • ClusterIP:默认值,它是kubernetes系统自动分配的虚拟IP,只能在集群内部访问。

  • NodePort:将Service通过指定的Node上的端口暴露给外部,通过此方法,就可以在集群外部访问服务。

  • LoadBalancer:使用外接负载均衡器完成到服务的负载分发,注意此模式需要外部云环境的支持。

  • ExternalName:把集群外部的服务引入集群内部,直接使用。

6.1.2.ClusterIP类型service
  • 只允许集群内部访问
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
  • 这类Service不会分配Cluster IP,如果想要访问Service,只能通过Service的域名进行查询。

  • 创建service-headliness.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的端口
6.2.4.NodePort类型的Service
  • NodePort的工作原理就是将Service的端口映射到Node的一个端口上,然后就可以通过NodeIP:NodePort来访问Service了。

  • 创建service-nodeport.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:
kubectl get svc service-nodeport -n dev -o wide
6.1.5.LoadBalancer类型的Service
  • LoadBalancer和NodePort很相似,目的都是向外部暴露一个端口,区别在于LoadBalancer需要在集群的外部再配置一个负载均衡设备,外部服务发送到这个设备上的请求,会被设备负载之后转发到集群中。
6.1.6. ExternalName类型的Service
  • ExternalName类型的Service用于引入集群外部的服务,它通过externalName属性指定一个服务的地址,然后在集群内部访问此Service就可以访问到外部的服务了。

  • 创建service-externalname.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文件,内容如下:

apiVersion: v1
kind: Endpoints
metadata:
  name: mysql-214
  namespace: app
subsets:
  - addresses:
    - ip: 192.168.2.214
    ports:
    - port: 16303
  • 创建 service-mysql.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 文件
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
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),如果不指定,会默认分配
    • 测试访问
#查看service
kubectl get svc service-nodeport -n app -o wide
或者
kubectl describe service service-nodeport -n app

kubernetes完整学习笔记_第16张图片

6.2.ingress 资源
  • Service对集群之外暴露服务的主要方式有两种:NodePort和LoadBalancer,但是这两种方式,都有一定的缺点:

    • NodePort方式的缺点是会占用很多集群机器的端口,那么当集群服务变多的时候,这个缺点就愈发明显。
    • LoadBalancer的缺点是每个Service都需要一个LB,浪费,麻烦,并且需要kubernetes之外的设备的支持。
  • 基于这种现状,kubernetes提供了Ingress资源对象,Ingress只需要一个NodePort或者一个LB就可以满足暴露多个Service的需求。

6.2.1安装ingress需要的环境
#wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml
#wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/provider/baremetal/service-nodeport.yaml
[root@k8s_master ~]# wget --no-check-certificate https://oss.linuxtxc.com/ingress-controller.zip
[root@k8s_master ~]# unzip ingress-controller.zip
[root@k8s_master ~]# cd ingress-controller/
[root@k8s_master ~]# kubectl apply -f  ./

kubernetes完整学习笔记_第17张图片

6.2.2.Http代理
  • 为服务创建 service,yaml文件内容如下:
apiVersion: v1 
kind: Service 
metadata: 
  name: nginx-service
  namespace: app
spec:
  selector: # 标签选择器,用于确定当前Service代理那些Pod
    app: nginx
  type: ClusterIP
  ports: # 
    - port: 80 # Service端口
      protocol: TCP 
      targetPort : 80
---

apiVersion: v1
kind: Service
metadata:
  name: tomcat-service
  namespace: app
spec:
  selector:
    app: tomcat
  type: ClusterIP
  ports:
  - port: 8080
    targetPort: 8080
  • 创建ingress-http.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
  - host: tomcat.linuxtxc.com
    http:
      paths:
      - path: /
        backend:
          serviceName: tomcat-service
          servicePort: 8080
  • 查看ingress端口:
kubectl get ing ingress-http -n app

kubernetes完整学习笔记_第18张图片

#查看访问ingress端口
kubectl get service -n ingress-nginx

image-20220411203347463

  • 访问URL:http://nginx.linuxtxc.com:32443(可以在本地hosts文件中添加解析访问)

kubernetes完整学习笔记_第19张图片

6.2.3.Https代理
为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
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
  • 查看ingress访问端口
kubectl get service -n ingress-nginx

7.k8s的数据存储

  • Volume是Pod中能够被多个容器访问的共享目录,它被定义在Pod上,然后被一个Pod里面的多个容器挂载到具体的文件目录下,kubernetes通过Volume实现同一个Pod中不同容器之间的数据共享以及数据的持久化存储。Volume的生命周期不和Pod中的单个容器的生命周期有关,当容器终止或者重启的时候,Volume中的数据也不会丢失。

  • kubernetes的Volume支持多种类型,比较常见的有下面的几个:

    • 简单存储:EmptyDir、HostPath、NFS。
    • 高级存储:PV、PVC。
    • 配置存储:ConfigMap、Secret。
7.1.EmptyDir
  • 它是最基础的volume类型,一个EmptyDir就是Host 上的一个空目录,当pod被分配到 Node时创建,它的初始内容为空,当pod 被销毁时,EmptyDir中的数据也会永久删除

  • EmptyDir的用途如下:

    • 临时空间,例如用于某些应用程序运行时所需的临时目录,且无须永久保留。
    • 一个容器需要从另一个容器中获取数据的目录(多容器共享目录)。
  • 创建volume-emptydir.yaml,内容如下:(一个容器从一个容器中获取数据的目录(多容器共享目录))

apiVersion: v1
kind: Pod
metadata:
  name: volume-emptydir
  namespace: dev
spec:
  containers:
    - name: nginx
      image: nginx:1.17.1
      imagePullPolicy: IfNotPresent
      ports:
        - containerPort: 80
      volumeMounts: # 将logs-volume挂载到nginx容器中对应的目录,该目录为/var/log/nginx
        - name: logs-volume
          mountPath: /var/log/nginx
    - name: busybox
      image: busybox:1.30
      imagePullPolicy: IfNotPresent
      command: ["/bin/sh","-c","tail -f /logs/access.log"] # 初始命令,动态读取指定文件
      volumeMounts:  #将logs-volume挂载到busybox容器中的对应目录,该目录为/logs
        - name: logs-volume
          mountPath: /logs
  volumes: # 声明volume,name为logs-volume,类型为emptyDir
    - name: logs-volume
      emptyDir: {}
  • 查看pod
kubectl get pod volume-emptydir -n dev -o wide

image-20220403081120258

  • 访问pod中的 nginx
 curl 172.16.67.8

kubernetes完整学习笔记_第20张图片

  • 查看指定容器的标准输出:
kubectl logs -f volume-emptydir -n dev -c busybox

image-20220403081603426

7.2.HostPath
  • HostPath就是将Node主机中的一个实际目录挂载到Pod中,以供容器使用,这样的设计就可以保证Pod销毁了,但是数据依旧可以保存在Node主机上。

  • 创建volume-hostpath.yaml文件,内容如下:

apiVersion: v1
kind: Pod
metadata:
  name: volume-hostpath
  namespace: dev
spec:
  containers:
    - name: nginx
      image: nginx:1.17.1
      imagePullPolicy: IfNotPresent
      ports:
        - containerPort: 80
      volumeMounts: # 将logs-volume挂载到nginx容器中对应的目录,该目录为/var/log/nginx
        - name: logs-volume
          mountPath: /var/log/nginx
    - name: busybox
      image: busybox:1.30
      imagePullPolicy: IfNotPresent
      command: ["/bin/sh","-c","tail -f /logs/access.log"] # 初始命令,动态读取指定文件
      volumeMounts: # 将logs-volume挂载到busybox容器中的对应目录,该目录为/logs
        - name: logs-volume
          mountPath: /logs
  volumes: # 声明volume,name为logs-volume,类型为hostPath
    - name: logs-volume
      hostPath:
        path: /opt/logs/nginx
        type: DirectoryOrCreate # 目录存在就使用,不存在就先创建再使用

type的值的说明:

  • DirectoryOrCreate:目录存在就使用,不存在就先创建后使用。

  • Directory:目录必须存在。

  • FileOrCreate:文件存在就使用,不存在就先创建后使用。

  • File:文件必须存在。

  • Socket:unix套接字必须存在。

  • CharDevice:字符设备必须存在。

  • BlockDevice:块设备必须存在。

查看pod

kubectl get pod volume-hostpath -n dev -o wide

image-20220403084457732

  • 访问Pod中的Nginx:
curl  172.16.34.7

kubernetes完整学习笔记_第21张图片

  • 去node节点找到hostPath映射的目录(我是在node01上,如果在此目录中创建文件,到容器中也是可以看到的。)

image-20220403084840452

7.3.NFS
  • HostPath虽然可以解决数据持久化的问题,但是一旦Node节点故障了,Pod如果转移到别的Node节点上,又会出现问题,此时需要准备单独的网络存储系统,比较常用的是NFS

  • NFS是一个网络文件存储系统,可以搭建一台NFS服务器,然后将Pod中的存储直接连接到NFS系统上,这样,无论Pod在节点上怎么转移,只要Node和NFS的对接没有问题,数据就可以成功访问。

7.3.1.安装NFS服务
  • 下载软件包
yum install -y nfs-utils rpcbind
  • 准备一个共享目录:
mkdir -pv /opt/data
  • vim /etc/exports,将共享目录以读写权限暴露给172.16.8.0/24网段中的所有主机:
/opt/data 172.16.8.0/24(rw,no_root_squash)

#加载配置
exportfs -r

#启动nfs服务
systemctl start  rpcbind
systemctl enable rpcbind
systemctl start  nfs-server
systemctl enable nfs-server
  • K8s node上安装nfs-utils ,但并不启动服务
yum -y install nfs-utils

#查看NFS挂载情况(-d:仅显示已被NFS客户端加载的目录; -e:显示NFS服务器上所有的共享目录。)
showmount -e  172.16.8.217

kubernetes完整学习笔记_第22张图片

  • 高可用备份方式,可以选择在某一节点上执行:
mount -t  nfs 172.16.8.217:/opt/data /mnt
7.3.2.pod挂载案例
  • 创建volume-nfs.yaml文件,内容如下:
apiVersion: v1
kind: Pod
metadata:
  name: volume-nfs
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.1
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 80
    volumeMounts: # 将logs-volume挂载到nginx容器中对应的目录,该目录为/var/log/nginx
    - name: logs-volume
      mountPath: /var/log/nginx
  - name: busybox
    image: busybox:1.30
    imagePullPolicy: IfNotPresent
    command: ["/bin/sh","-c","tail -f /logs/access.log"] # 初始命令,动态读取指定文件
    volumeMounts: # 将logs-volume挂载到busybox容器中的对应目录,该目录为/logs
    - name: logs-volume
      mountPath: /logs
  volumes: # 声明volume
  - name: logs-volume
    nfs:
      server: 172.16.8.217 # NFS服务器地址
      path: /opt/data/nfs # 共享文件路径
  • 在NFS服务器上查看 文件共享情况

kubernetes完整学习笔记_第23张图片

7.4.PV与PVC
7.4.1.PV(Persistent Volume)
  • 是持久化卷的意思,是对底层的共享存储的一种抽象。它和底层具体的共享存储技术有关,并通过插件完成和共享存储的对接。(它没有namespace区别的划分)
pv的关键配置参数说明:
存储类型:底层实际存储的类型,kubernetes支持多种存储类型,每种存储类型的配置有所不同。
存储能力(capacity):目前只支持存储空间的设置(storage=1Gi),不过未来可能会加入IOPS、吞吐量等指标的配置。
访问模式(accessModes):
  用来描述用户应用对存储资源的访问权限,访问权限包括下面几种方式:
    ReadWriteOnce(RWO):读写权限,但是只能被单个节点挂载。
    ReadOnlyMany(ROX):只读权限,可以被多个节点挂载。
    ReadWriteMany(RWX):读写权限,可以被多个节点挂载。
  需要注意的是,底层不同的存储类型可能支持的访问模式不同。
回收策略( persistentVolumeReclaimPolicy):
  当PV不再被使用之后,对其的处理方式,目前支持三种策略:
    Retain(保留):保留数据,需要管理员手动清理数据。
    Recycle(回收):清除PV中的数据,效果相当于rm -rf /volume/*。
    Delete(删除):和PV相连的后端存储完成volume的删除操作,常见于云服务器厂商的存储服务。
  需要注意的是,底层不同的存储类型可能支持的回收策略不同。
存储类别(storageClassName):PV可以通过storageClassName参数指定一个存储类别。
  具有特定类型的PV只能和请求了该类别的PVC进行绑定。
  未设定类别的PV只能和不请求任何类别的PVC进行绑定。
状态(status):一个PV的生命周期,可能会处于4种不同的阶段。
  Available(可用):表示可用状态,还未被任何PVC绑定。
  Bound(已绑定):表示PV已经被PVC绑定。
  Released(已释放):表示PVC被删除,但是资源还没有被集群重新释放。
  Failed(失败):表示该PV的自动回收失败。
  • 创建pv-nfs.yaml,内容如下(使用的之前创建的NFS服务):
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv1
spec:
  nfs: # 存储类型吗,和底层正则的存储对应
    path: /opt/data/pv1
    server: 172.16.8.217
  capacity: # 存储能力,目前只支持存储空间的设置
    storage: 1Gi
  accessModes: # 访问模式
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain # 回收策略

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv2
spec:
  nfs: # 存储类型吗,和底层正则的存储对应
    path: /opt/data/pv2   ## 共享文件路径
    server: 172.16.8.217
  capacity: # 存储能力,目前只支持存储空间的设置
    storage: 2Gi
  accessModes: # 访问模式
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain # 回收策略
  
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv3
spec:
  nfs: # 存储类型吗,和底层正则的存储对应
    path: /opt/data/pv3
    server: 172.16.8.217
  capacity: # 存储能力,目前只支持存储空间的设置
    storage: 3Gi
  accessModes: # 访问模式
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain # 回收策略
  • 查看PV
kubectl get  pv

kubernetes完整学习笔记_第24张图片

7.4.2.PVC(Persistent Volume Claim)
  • 是资源的申请,用来声明对存储空间、访问模式、存储类别需求信息,下面是PVC的资源清单文件:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc
  namespace: dev
spec:
  accessModes:  #访问模式
    - ReadWriteMany 
  selector: # 采用标签对PV选择
  storageClassName: # 存储类别
  resources: # 请求空间
    requests:
      storage: 5Gi

PVC的关键配置参数说明:

  • 访客模式(accessModes):用于描述用户应用对存储资源的访问权限。

  • 用于描述用户应用对存储资源的访问权限:

    • 选择条件(selector):通过Label Selector的设置,可使PVC对于系统中已存在的PV进行筛选。
    • 存储类别(storageClassName):PVC在定义时可以设定需要的后端存储的类别,只有设置了该class的pv才能被系统选出。
    • 资源请求(resources):描述对存储资源的请求。
  • 创建pvc-test.yaml,内容如下:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc1
  namespace: dev
spec:
  accessModes: # 访客模式
    - ReadWriteMany
  resources: # 请求空间
    requests:
      storage: 1Gi

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc2
  namespace: dev
spec:
  accessModes: # 访客模式
    - ReadWriteMany
  resources: # 请求空间
    requests:
      storage: 1Gi

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc3
  namespace: dev
spec:
  accessModes: # 访客模式
    - ReadWriteMany
  resources: # 请求空间
    requests:
      storage: 5Gi
  • 查看PVC
kubectl get  pvc -n dev -o wide
#pvc3未绑定,是因为没有满足需求的pv

kubernetes完整学习笔记_第25张图片

  • 查看PV
kubectl get pv

kubernetes完整学习笔记_第26张图片

7.4.3.创建pod使用PVC
  • 创建pvc-pod.yaml文件,内容如下:
apiVersion: v1
kind: Pod
metadata:
  name: pod1
  namespace: dev
spec:
  containers:
  - name: busybox
    image: busybox:1.30
    command: ["/bin/sh","-c","while true;do echo pod1 >> /root/out.txt; sleep 10; done;"]
    volumeMounts:
    - name: volume
      mountPath: /root/
  volumes:
    - name: volume
      persistentVolumeClaim:
        claimName: pvc1
        readOnly: false

---
apiVersion: v1
kind: Pod
metadata:
  name: pod2
  namespace: dev
spec:
  containers:
    - name: busybox
      image: busybox:1.30
      command: ["/bin/sh","-c","while true;do echo pod1 >> /root/out.txt; sleep 10; done;"]
      volumeMounts:
        - name: volume
          mountPath: /root/
  volumes:
    - name: volume
      persistentVolumeClaim:
        claimName: pvc2
        readOnly: false
  • 查看NFS服务器上共享的的目录

kubernetes完整学习笔记_第27张图片

  • 资源释放:

    • 用户删除PVC来释放PV。
    • 当存储资源使用完毕后,用户可以删除PVC,和该PVC绑定的PV将会标记为“已释放”,但是还不能立刻和其他的PVC进行绑定。通过之前PVC写入的数据可能还留在存储设备上,只有在清除之后该PV才能再次使用。
  • 资源回收:

    • kubernetes根据PV设置的回收策略进行资源的回收。
    • 对于PV,管理员可以设定回收策略,用于设置与之绑定的PVC释放资源之后如何处理遗留数据的问题。只有PV的存储空间完成回收,才能供新的PVC绑定和使用。

创建PVC后一直绑定不了PV的原因

  • ①PVC的空间申请大小比PV的空间要大。

  • ②PVC的storageClassName和PV的storageClassName不一致。

  • ③PVC的accessModes和PV的accessModes不一致。

7.4.4.使用glusterfs 创建 pv,并挂载使用
#glusterfs分布式存储部署
wget http://oss.linuxtxc.com/%E7%AC%94%E8%AE%B0/%E5%88%86%E5%B8%83%E5%BC%8F%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9Fglusterfs%E5%AE%89%E8%A3%85%E6%96%87%E6%A1%A3.md

#kubernetes 所有节点都安装 glusterfs客户端
yum install -y glusterfs glusterfs-fuse
  • 创建glusterfs的endpoints
apiVersion: v1
kind: Namespace
metadata:
  name: app

---
apiVersion: v1
kind: Endpoints
metadata:
  name: glusterfs-cluster
  namespace: app
subsets:
- addresses:
  - ip: 172.16.8.212
  - ip: 172.16.8.213
  - ip: 172.16.8.214
  ports:
  - port: 49152
    protocol: TCP
  • 创建pv使用glusterfs
apiVersion: v1
kind: PersistentVolume
metadata:
  name: glusterfs-pv01
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteMany
  glusterfs:
    endpoints: glusterfs-cluster
    path: app-data  #创建的存储卷
    readOnly: false

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: glusterfs-pv02
spec:
  capacity:
    storage: 2Gi
  accessModes:
    - ReadWriteMany
  glusterfs:
    endpoints: glusterfs-cluster
    path: app-data  #创建的存储卷
    readOnly: false
  • 创建PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: glusterfs-pvc01
  namespace: app
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 2Gi
  • 创建使用Glusterfs卷的应用
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: app
spec:
  replicas: 2
  selector:
    matchLabels:
      name: nginx
  template:
    metadata:
      labels:
        name: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          ports:
            - containerPort: 80
          volumeMounts:
            - name: nginxglusterfs
              mountPath: "/usr/share/nginx/html"
      volumes:
      - name: nginxglusterfs
        persistentVolumeClaim:
          claimName: glusterfs-pvc
  • 查看容器是否成功挂载
kubectl  exec -it  deployment-glu-pv-9fb5fb64-kl48h -n app  mount  | grep app-data

kubernetes完整学习笔记_第28张图片

7.5.configmap
  • ConfigMap是一种API对象,用来将非加密数据保存到键值对中。可以用作环境变量、命令行参数或者存储卷中的配置文件。
  • ConfigMap可以将环境变量配置信息和容器镜像解耦,便于应用配置的修改。如果需要存储加密信息时可以使用Secret对象。
7.5.1.使用命令行创建
(1)使用目录创建
kubectl create configmap configmap名 --from-file=/path (--from-file,指定在目录下的所有文件都会被用在ConfigMap里面创建一个键值对,键的名字就是文件名,值就是文件的内容)

(2)使用文件创建
kubectl create configmap configmap名 --from-file=./file1 --from-file=./file2 (--from-file,可以使用多次,同样键为文件名,值为文件中的内容)

(3)通过key-value字符串创建
kubectl create configmap configmap名 --from-literal=key1=123 --from-literal=key2=234

(4)通过env文件创建
kubectl create configmap configmap名 --from-env-file=env.txt 
其中,env.txt的文件格式为:
key1=***
key2=***
  • 使用ConfigMap有以下几个限制条件:

    • ConfigMap必须在pod之前创建
    • configmap受namespace的限制,只能相同namespace的pod才可以引用
7.5.2.通过Volume 方式挂载
  • 将ConfigMap中的内容挂载为容器内部的文件或目录

  • 创建 configmap-nginx.yaml,内容如下:

apiVersion: v1
kind: ConfigMap
metadata: 
  name: configmap
  namespace: web
data:
  stream.conf: |   
    stream.conf {
      server {
        listen 1550;
        proxy_pass  192.168.3.125:16303;
    }
    
     }
 kubectl get cm -n web

image-20220405135908643

  • 将configmap中的配置通过volume挂载
apiVersion: v1
kind: Pod
metadata:
  name: pod-configmap
  namespace: web
spec:
  containers:
  - name: nginx
    image: nginx:1.17.1
    volumeMounts: 
    - name: config
      mountPath: /etc/nginx/vhosts   #没有则会自动创建,目录下有文件则会覆盖掉
  volumes:
  - name: config
    configMap:
      name: configmap    #指的是要从哪个configmap里读取数据
kubectl exec -it pod-configmap -n web /bin/sh

kubernetes完整学习笔记_第29张图片

7.5.3.通过SubPath 使原目录文件不被覆盖
  • 创建 configmap-php.yaml,内容如下:
apiVersion: v1
kind: ConfigMap
metadata: 
  name: configmap-php
  namespace: web
data:
  index.php: | 
    
kubectl get cm -n web

image-20220406114115925

  • 创建 volume-configmap-php.yaml,内容如下
apiVersion: v1
kind: Pod
metadata:
  name: pod-configmap-php
  namespace: web
spec:
  containers:
  - name: nginx
    image: nginx:1.17.1
    volumeMounts: 
    - name: config
      mountPath: /usr/share/nginx/html/index.php   
      subPath: index.php   #与configmap中的key相同
  volumes:
  - name: config
    configMap:
      name: configmap-php    #指的是要从哪个configmap里读取数据
 kubectl exec -it pod-configmap-php -n web /bin/sh

kubernetes完整学习笔记_第30张图片

  • 只覆盖指定的文件
apiVersion: v1
kind: Pod
metadata:
  name: nginx-configmap
  namespace: app
spec:
  containers:
    - name: nginx
      image: nginx:1.17.1
      command: [ "/bin/sh", "-c", "sleep 3600" ]
      volumeMounts:
      - name: config
        mountPath: /etc/nginx/nginx.conf
        subPath: nginx.conf #subPath:要覆盖文件的相对路径
  volumes:
    - name: config
      configMap:
        name: configmap-nginx    #configMap的名称
        items:        #用于只挂载configmap中特定的key
         - key: nginx.conf   #ConfigMap中key的名称
           path: nginx.conf # 此处的path相当于 mv nginx.conf nginx.conf
7.6.Secret
  • 跟configMap非常类似的对象,它主要是用于存储敏感信息,例如密码,密钥,证书等等。

  • Secret有三种类型:

    • Opaque
    • kubernetes.io/dockerconfigjson
    • ServiceAccount
7.6.1.Opaque
  • base64 编码格式的 Secret,用来存储密码、密钥等;但数据也可以通过base64 –decode解码得到原始数据,所有加密性很弱。
#使用命令行 创建secret
 (1)kubectl create secret generic db-user-pass --from-file=./username.txt --from-file=./password.txt
 (2)kubectl create secret generic db-user-pass --from-literal=username=admin --from-literal=password=1f2d1e2e67df
 
#手动创建base64加密 
echo -n 'admin' | base64
echo -n '1f2d1e2e67df' | base64

#解密
echo 'MWYyZDFlMmU2N2Rm' | base64 --decode
  • 创建 secret-opaque.yaml,内容如下:
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
  namespace: dev
type: Opaque
data:
  username: YWRtaW4=    #修改为base64加密后的
  password: MWYyZDFlMmU2N2Rm
 kubectl get secret mysecret -n dev -o yaml

kubernetes完整学习笔记_第31张图片

  • 也可以将一个非 base64 编码的字符串直接放入 Secret 中, 当创建或更新该 Secret 时,此字段将被编码。
apiVersion: v1
kind: Secret
metadata:
  name: web-secret
  namespace: web
type: Opaque
stringData:
  config.yaml: |
    apiUrl: "https://my.api.com/api/v1"
    username: admin
    password: 123456 
  • 创建pod-secret.yaml,将secert 挂载到 pod中,内容如下:
apiVersion: v1
kind: Pod
metadata:
  name: pod-secret
  namespace: dev
spec:
  containers:
    - name: nginx
      image: nginx:1.17.1
      volumeMounts:
        - name: config
          mountPath: /secret/config
          readOnly: true
  volumes:
    - name: config
      secret:
        secretName: mysecret
kubectl exec -it pod-secret -n dev /bin/sh

kubernetes完整学习笔记_第32张图片

  • 只挂载Secret中特定的key
apiVersion: v1
kind: Pod
metadata:
  name: pod-secret-01
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.1
    volumeMounts:
    - name: secret
      mountPath: /opt
      readOnly: true
  volumes:
  - name: secret
    secret:
      secretName: mysecret
      items:
      - key: username
        path: cert/username    #username 将存储在/opt/cert/username 下
kubectl exec -it pod-secret-01 -n dev /bin/sh

kubernetes完整学习笔记_第33张图片

  • 将Secret设置为环境变量
apiVersion: v1
kind: Pod
metadata:
  name: secret-env-pod
spec:
  containers:
  - name: redis
    image: redis
    env:
      - name: SECRET_USERNAME
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: username
      - name: SECRET_PASSWORD
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: password
7.6.2.kubernetes.io/dockerconfigjson
  • 用来存储私有docker registry的认证信息。
kubectl create secret docker-registry myregistrykey --docker-server=192.168.3.124 --docker-username=admin --docker-password=admin123 --docker-email=<your-email> --namespace=dev
  • 在创建 Pod 的时候,通过 imagePullSecrets 来引用刚创建的 myregistrykey
apiVersion: v1
kind: Pod
metadata:
  name: dev
spec:
  containers:
    - name: foo
      image: janedoe/awesomeapp:v1
  imagePullSecrets:
    - name: myregistrykey
7.6.3.ServiceAccount
  • 用来访问Kubernetes API,由Kubernetes自动创建,并且会自动挂载到Pod的 /run/secrets/kubernetes.io/serviceaccount 目录中。
  • 每个namespace下有一个名为default的默认的ServiceAccount对象,这个ServiceAccount里有一个名为Tokens的可以作为Volume一样被Mount到Pod里的Secret,当Pod启动时这个Secret会被自动Mount到Pod的指定目录下,用来协助完成Pod中的进程访问API Server时的身份鉴权过程。
#创建一个sa 名称为admin
kubectl create  serviceaccount admin -n dev
  • 如果一个Pod在定义时没有指定spec.serviceAccountName属性,则会默认赋值为default,可进行如下指定
apiVersion: v1
kind: Pod
metadata:
  name: sa-demo
  namespace: dev
  labels:
    app: myapp
    release: canary
spec:
  containers:
  - name: myapp
    image: nginx:1.17.2
    ports:
    - name: nginx-port
      containerPort: 80
  serviceAccountName: admin  #此处指令为指定sa的名称
7.7.GlusterFS+Heketi实现volume动态扩容
  • SC:是StorageClass的缩写,表示存储类;这种资源主要用来对pv资源的自动供给提供接口;所谓自动供给是指用户无需手动创建pv,而是在创建pvc时对应pv会由persistentVolume-controller自动创建并完成pv和pvc的绑定;使用sc资源的前提是对应后端存储必须支持restfull类型接口的管理接口,并且pvc必须指定对应存储类名称来引用SC;简单讲SC资源就是用来为后端存储提供自动创建pv并关联对应pvc的接口;

  • Heketi是一个提供RESTful API管理GlusterFS卷的框架,便于管理员对GlusterFS进行操作:

#yum下载
#wget https://mirrors.aliyun.com/centos/7/storage/x86_64/gluster-9/Packages/h/heketi-9.0.0-1.el7.x86_64.rpm
wget  http://oss.linuxtxc.com/deploy/rpm/heketi-9.0.0-1.el7.x86_64.rpm

#wget https://mirrors.aliyun.com/centos/7/storage/x86_64/gluster-9/Packages/h/heketi-client-9.0.0-1.el7.x86_64.rpm
wget http://oss.linuxtxc.com/deploy/rpm/heketi-client-9.0.0-1.el7.x86_64.rpm
7.7.1.安装 heketi
#安装rpm包,我只在master上安装
yum  http://oss.linuxtxc.com/deploy/rpm/heketi-9.0.0-1.el7.x86_64.rpm
yum  http://oss.linuxtxc.com/deploy/rpm/heketi-client-9.0.0-1.el7.x86_64.rpm
  • 修改service文件
vim /usr/lib/systemd/system/heketi.service
......................
 [Unit]
Description=Heketi Server

[Service]
Type=simple
WorkingDirectory=/var/lib/heketi
EnvironmentFile=/etc/heketi/heketi.json
User=root
ExecStart=/usr/bin/heketi --config=/etc/heketi/heketi.json
Restart=on-failure
StandardOutput=syslog
StandardError=syslog

[Install]
WantedBy=multi-user.target
  • 修改heketi配置文件
vim /etc/heketi/heketi.json
.............................
#修改端口,防止端口冲突
  "port": "18080",
......
#允许认证
  "use_auth": true,
......
#admin用户的key改为adminkey
      "key": "adminkey"
#普通用户的key改为userkey  
      "key": "userkey"
......
#修改执行插件为ssh,并配置ssh的所需证书,注意要能对集群中的机器免密ssh登陆,使用ssh-copy-id把pub key拷到每台glusterfs服务器上
    "executor": "ssh",
    "sshexec": {
      "keyfile": "/etc/heketi/heketi_key",
      "user": "root",
      "port": "22",
      "fstab": "/etc/fstab"
    },
......
# 定义heketi数据库文件位置
    "db": "/var/lib/heketi/heketi.db"
......
#调整日志输出级别
    "loglevel" : "warning"
  • 配置ssh密钥
[root@k8s-master heketi]# ssh-keygen -f /etc/heketi/heketi_key -t rsa -N ''

[root@k8s-master heketi]# ssh-copy-id -i /etc/heketi/heketi_key.pub 172.16.8.212
[root@k8s-master heketi]# ssh-copy-id -i /etc/heketi/heketi_key.pub 172.16.8.213
[root@k8s-master heketi]# ssh-copy-id -i /etc/heketi/heketi_key.pub 172.16.8.214
  • 验证登录
ssh -i /etc/heketi/heketi_key  [email protected]

image-20220409173300047

  • 启动heketi
systemctl  start  heketi
systemctl enable  heketi 
  • 查看heketi服务状态
systemctl status heketi

kubernetes完整学习笔记_第34张图片

7.7.2.heketi添加glusterfs
  • Heketi添加cluster
 heketi-cli --user admin --server http://172.16.8.124:18080 --secret adminkey --json  cluster create
.................................
{"id":"7a263332ed6bc432f7fa81e65e021542","nodes":[],"volumes":[],"block":true,"file":true,"blockvolumes":[]}

image-20220409181609507

  • 将所有glusterfs节点作为node添加到cluster
[root@k8s-master heketi]# heketi-cli --server http://172.16.8.124:18080   --user "admin" --secret "adminkey"   node add --cluster "7a263332ed6bc432f7fa81e65e021542"  --management-host-name  172.16.8.212  --storage-host-name 172.16.8.212 --zone 1

[root@k8s-master heketi]# heketi-cli --server http://172.16.8.124:18080   --user "admin" --secret "adminkey"   node add --cluster "7a263332ed6bc432f7fa81e65e021542"  --management-host-name  172.16.8.213  --storage-host-name 172.16.8.213 --zone 1

[root@k8s-master heketi]# heketi-cli --server http://172.16.8.124:18080   --user "admin" --secret "adminkey"   node add --cluster "7a263332ed6bc432f7fa81e65e021542"  --management-host-name  172.16.8.214  --storage-host-name 172.16.8.214 --zone 1

注:要保存每个glusterfs节点ID

kubernetes完整学习笔记_第35张图片

  • 添加device,volume是基于device创建的,目前heketi仅支持使用裸分区或裸磁盘(未格式化)添加为device,不支持文件系统,所以每个glusterfs节点上要有未格式化的磁盘
[root@k8s-master heketi]# heketi-cli --server http://172.16.8.124:18080   --user "admin" --secret "adminkey"    --json device add --name="/dev/sdb" --node "3aee8b6287717c18c72fbcc547e8bff4"

[root@k8s-master heketi]# heketi-cli --server http://172.16.8.124:18080   --user "admin" --secret "adminkey"    --json device add --name="/dev/sdb" --node "833b827e2d72c73a597c7d82a5ebdbc5"

[root@k8s-master heketi]# heketi-cli --server http://172.16.8.124:18080   --user "admin" --secret "adminkey"    --json device add --name="/dev/sdb" --node "968afeb52b8924cac7ffac6db3963e03"

image-20220411120811021

  • 创建一个大小为2G,副本为2的volume
[root@k8s-master dev]# heketi-cli --server http://172.16.8.124:18080   --user "admin" --secret "adminkey"  volume create --size 2 --replica 2

#通过下面信息,可以看到Heketi创建了名为vol_15249e32eb410cabe764e4a06e254a7e的数据卷。

kubernetes完整学习笔记_第36张图片

7.7.3.创建资源使用volume
  • 创建storageclass-glusterfs.yaml,内容如下:
apiVersion: v1
kind: Secret
metadata:
  name: heketi-secret
  namespace: app
data:
  # echo -n "mypassword" | base64 / base64 encoded "password"
  key: bXlwYXNzd29yZA==
type: kubernetes.io/glusterfs

---
apiVersion: storage.k8s.io/v1beta1
kind: StorageClass
metadata:
  name: glusterfs
provisioner: kubernetes.io/glusterfs
allowVolumeExpansion: true
parameters:
  resturl: "http://172.16.8.124:18080"
  clusterid: "7a263332ed6bc432f7fa81e65e021542"
  restauthenabled: "true"
  restuser: "admin"
  #secretNamespace: "default"
  #secretName: "heketi-secret"
  restuserkey: "adminkey"
  gidMin: "40000"
  gidMax: "50000"
  volumetype: "replicate:2"
kubectl get storageclass -n app

image-20220411125743644

  • 创建glusterfs-pvc.yaml内容如下:
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: glusterfs-pvc
  namespace: app
  annotations:
    volume.beta.kubernetes.io/storage-class: "glusterfs"
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 2Gi     
 kubectl get pvc -n app
 #有绑定的volume才算创建成功,同时PV也会自动创建

image-20220411150120802

  • 创建 mysql-deployment.yaml,内容如下:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
  namespace: app
spec:
  selector:
    matchLabels:
      name: mysql
  template:
    metadata:
      labels:
        name: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:5.7
        imagePullPolicy: IfNotPresent
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: root123456
        ports:
          - containerPort: 3306
        volumeMounts:
        - name: glusterfs-mysql-data
          mountPath: "/var/lib/mysql"
      volumes:
        - name: glusterfs-mysql-data
          persistentVolumeClaim:
            claimName: glusterfs-pvc
            readOnly: false
  • 查看volume挂载情况
kubectl exec -it mysql-5b94895868-n6xld -n app mount | grep 172

image-20220411151453503

  • 查看glusterfs集群状态
gluster  volume  status

kubernetes完整学习笔记_第37张图片

7.7.4.动态修改PVC
  • 查看当前PVC容量

image-20220411182503833

#修改yaml配置
vim glusterfs-pvc.yaml

kubectl apply -f glusterfs-pvc.yaml
  • 再次查看 PVC
 kubectl get pvc -n app

image-20220411182936770


8.k8s的安全认证

8.1.概念描述

● API Server是访问和管理资源对象的唯一入口。任何一个请求访问API Server,都要经过下面的三个流程:
○ ① Authentication(认证):身份鉴别,只有正确的账号才能通过认证。
○ ② Authorization(授权):判断用户是否有权限对访问的资源执行特定的动作。
○ ③ Admission Control(注入控制):用于补充授权机制以实现更加精细的访问控制功能。

UserAccount:用于限制用户账号对 kubernetes集群资源访问的权限
ServiceAccount:用于为Pod的服务进程在访问kubernetes时提供身份标识。

API Server目前支持的几种授权策略
● AlwaysDeny:表示拒绝所有请求,一般用于测试。
● AlwaysAllow:允许接收所有的请求,相当于集群不需要授权流程(kubernetes默认的策略)。
● ABAC:基于属性的访问控制,表示使用用户配置的授权规则对用户请求进行匹配和控制。
● Webhook:通过调用外部REST服务对用户进行授权。
● Node:是一种专用模式,用于对kubelet发出的请求进行访问控制。
● RBAC:基于角色的访问控制(kubeadm安装方式下的默认选项)。

● RBAC(Role Based Access Control) : 基于角色的访问控制,主要是在描述一件事情:给哪些对象授权了哪些权限。
● RBAC涉及到了下面几个概念:
○ 对象:User、Groups、ServiceAccount。
○ 角色:代表着一组定义在资源上的可操作的动作(权限)的集合。
○ 绑定:将定义好的角色和用户绑定在一起。

● RBAC引入了4个顶级资源对象:
○ Role、ClusterRole:角色,用于指定一组权限。
○ RoleBinding、ClusterRoleBinding:角色绑定,用于将角色(权限的集合)赋予给对象。

8.2.Role、ClusterRole
  • Role的资源清单文件:
# Role只能对命名空间的资源进行授权,需要指定namespace
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: authorization-role
  namespace: dev
rules:
  - apiGroups: [""]       # 支持的API组列表,""空字符串,表示核心API群
    resources: ["pods"]      # 支持的资源对象列表
    verbs: ["get","watch","list"]
  • ClusterRole的资源清单文件:
# ClusterRole可以对集群范围内的资源、跨namespace的范围资源、非资源类型进行授权
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: authorization-clusterrole
rules:
  - apiGroups: [""]      # 支持的API组列表,""空字符串,表示核心API群
    resources: ["pods"]       # 支持的资源对象列表
    verbs: ["get","watch","list"]
rules中的参数说明:
apiGroups:
  #支持的API组列表。
  "","apps","autoscaling","batch"。
resources:
  #支持的资源对象列表。 "services","endpoints","pods","secrets","configmaps","crontabs","deployments","jobs","nodes","rolebindings","clusterroles","daemonsets","replicasets","statefulsets","horizontalpodautoscalers","replicationcontrollers","cronjobs"。
verbs:
  #对资源对象的操作方法列表。
  "get", "list", "watch", "create", "update", "patch", "delete", "exec"。
8.3.RoleBinding、ClusterRoleBinding
  • 角色绑定用来把一个角色绑定到一个目标对象上,绑定目标可以是User、Group或者ServiceAccount。

  • RoleBinding的资源清单文件:

# RoleBinding可以将同一namespace中的subject对象绑定到某个Role下,则此Subject具有该Role定义的权限
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: authorization-role-binding
  namespace: dev
subjects:
  - kind: User
    name: test
    apiGroup: rbac.authorization.k8s.io  
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: authorization-role
  • ClusterRoleBinding的资源清单文件:
# ClusterRoleBinding在整个集群级别和所有namespaces将特定的subject与ClusterRole绑定,授予权限
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: authorization-clusterrole-binding
subjects:
  - kind: User
    name: test
    apiGroup: rbac.authorization.k8s.io
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: authorization-clusterrole
  • RoleBinding引用ClusterRole进行授权
    ○RoleBinding可以引用ClusterRole,对属于同一命名空间内ClusterRole定义的资源主体进行授权。
    ○ 一种很常用的做法是,集群管理员为集群范围预定义好一组规则(ClusterRole),然后在多个命名空间中重复使用这些ClusterRole。这样可以大幅度提高授权管理工作效率,也使得各个命名空间下的基础性授权规则和使用体验保持一致。
# 虽然authorization-clusterrole是一个集群角色,但是因为使用了RoleBinding
# 所以test用户只能读取dev命名空间中的资源
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: authorization-clusterrole-binding
subjects:
  - kind: User
    name: test
    apiGroup: rbac.authorization.k8s.io
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: authorization-clusterrole
8.4.RBAC案例
  • 创建一个只能管理dev命名空间下Pods资源的账号。
#创建用户的私钥
cd /etc/kubernetes/pki
(umask 077;openssl genrsa -out devuser.key 2048)

#创建证书签署请求(O:组织名 CN:用户名)
 openssl req -new -key devuser.key -out devuser.csr -subj "/CN=devuser/O=devgroup"

#签署证书
openssl x509 -req -in devuser.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out devuser.crt -days 3650

#设置集群、用户、上下文信息(不设置--kubeconfig,如--kubeconfig=/root/.devuser.config,则会默认放在家目录下的./kube 中)
kubectl config set-cluster kubernetes --embed-certs=true --certificate-authority=/etc/kubernetes/pki/ca.crt  --server=https://172.16.8.124:6443 

kubectl config set-credentials devuser --embed-certs=true --client-certificate=devuser.crt --client-key=devuser.key  

kubectl config set-context devuser@kubernetes --cluster=kubernetes --user=devuser 

#切换账号到devuser
kubectl config use-context devuser@kubernetes 
#查看(当前还没有权限执行当前操作,还需要对用户授权)
kubectl get pods -n dev

image-20220408135932946

  • 如果要使用linux的普通用户管理集群
[root@k8s_master ~]# useradd devuser
[root@k8s_master ~]# mkdir /home/devuser/.kube
[root@k8s_master ~]# cp .kube/config /home/devuser/.kube/
[root@k8s_master ~]# chown  -R devuser:devuser  /home/devuser/
  • 查看管理账号,并切换
#输出合并后的kubeconfig的内容,格式为 YAML,密文内容不会显示(--kubeconfig,可以指定只显示某个账户的kubeconfig内容)
kubectl  config view

#切回admin账户
kubectl config use-context kubernetes-admin@kubernetes
  • 创建Role和RoleBinding,为devuser授权

    • 创建dev-role.yaml文件,内容如下:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: dev-role
  namespace: dev
rules:
  - apiGroups: [""] # 支持的API组列表,""空字符串,表示核心API群
    resources: ["pods"] # 支持的资源对象列表
    verbs: ["get","watch","list"]

---

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: authorization-role-binding 
  namespace: dev
subjects:
  - kind: User
    name: devuser
    apiGroup: rbac.authorization.k8s.io 
roleRef:
  kind: Role 
  name: dev-role
  apiGroup: rbac.authorization.k8s.io
#切换成 devuser,再次查看
kubectl get pods -n dev

image-20220408140824760

8.5.准入控制
  • 通过了前面的认证和授权之后,还需要经过准入控制通过之后,API Server才会处理这个请求。

  • 准入控制是一个可配置的控制器列表,可以通过在API Server上通过命令行设置选择执行哪些注入控制器。

--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota,DefaultTolerationSeconds
  • 只有当所有的注入控制器都检查通过之后,API Server才会执行该请求,否则返回拒绝。

  • 当前可配置的Admission Control(准入控制)
    ○ AlwaysAdmit:允许所有请求。

    ○ AlwaysDeny:禁止所有请求,一般用于测试。

    ○ AlwaysPullImages:在启动容器之前总去下载镜像。

    ○ DenyExecOnPrivileged:它会拦截所有想在Privileged Container上执行命令的请求。

    ○ ImagePolicyWebhook:这个插件将允许后端的一个Webhook程序来完成admission controller的功能。

    ○ Service Account:实现ServiceAccount实现了自动化。

    ○ SecurityContextDeny:这个插件将使用SecurityContext的Pod中的定义全部失效。

    ○ ResourceQuota:用于资源配额管理目的,观察所有请求,确保在namespace上的配额不会超标。

    ○ LimitRanger:用于资源限制管理,作用于namespace上,确保对Pod进行资源限制。

    ○ InitialResources:为未设置资源请求与限制的Pod,根据其镜像的历史资源的使用情况进行设置。

    ○ NamespaceLifecycle:如果尝试在一个不存在的namespace中创建资源对象,则该创建请求将被拒 绝。当删除一个namespace时,系统将会删除该namespace中所有对象。

    ○ DefaultStorageClass:为了实现共享存储的动态供应,为未指定StorageClass或PV的PVC尝试匹配默认StorageClass,尽可能减少用户在申请PVC时所需了解的后端存储细节。

    ○ DefaultTolerationSeconds:这个插件为那些没有设置forgiveness tolerations并具有notready:NoExecute和unreachable:NoExecute两种taints的Pod设置默认的“容忍”时间,为5min。

    ○ PodSecurityPolicy:这个插件用于在创建或修改Pod时决定是否根据Pod的security context和可用的 PodSecurityPolicy对Pod的安全策略进行控制


9.k8s+prometheus+grafana实现集群监控

#下载yaml文件
https://oss.linuxtxc.com/k8s-prometheus-grafana.zip
#解压
unzip  k8s-prometheus-grafana.zip
#创建资源
cd k8s-prometheus-grafana/
kubectl apply -f node-exporter.yaml
kubectl apply -f grafana/
kubectl apply -f prometheus/
  • 访问prometheus(http://192.168.3.124:30003/targets)

kubernetes完整学习笔记_第38张图片

  • 访问node-exporter(http://192.168.3.124:31672/metrics)

kubernetes完整学习笔记_第39张图片

  • 访问Grafana(http://192.168.3.124:30106/login),默认用户密码均为admin

kubernetes完整学习笔记_第40张图片

  • 添加数据源,以下使用的代理模式(推荐),仅限k8s内部访问

kubernetes完整学习笔记_第41张图片

    • 也可以使用直接访问模式

kubernetes完整学习笔记_第42张图片

  • 导入面板:Dashboards->Import(导入面板,可以直接输入模板编号315在线导入,或者下载好对应的json模板文件本地导入)

kubernetes完整学习笔记_第43张图片

  • 查看展示效果

kubernetes完整学习笔记_第44张图片


10.k8s集群管理平台部署

10.1.kuboard安装
#下载
#wget http://oss.linuxtxc.com/deploy/yaml/kuboard-v3.yaml
wget https://addons.kuboard.cn/kuboard/kuboard-v3.yaml

kubectl apply -f kuboard-v3.yaml

访问 Kuboard

  • 在浏览器中打开链接 http://172.16.8.124:30080
  • 输入初始用户名和密码,并登录
    • 用户名: admin
    • 密码: Kuboard123

kubernetes完整学习笔记_第45张图片

10.2.kubesphere安装
#wget https://github.com/kubesphere/ks-installer/releases/download/v3.2.1/kubesphere-installer.yaml
#wget https://github.com/kubesphere/ks-installer/releases/download/v3.2.1/cluster-configuration.yaml

wget http://oss.linuxtxc.com/deploy/yaml/kubesphere/kubesphere-installer.yaml

wget http://oss.linuxtxc.com/deploy/yaml/kubesphere/cluster-configuration.yaml

kubectl apply -f  kubesphere-installer.yaml
kubectl apply -f  cluster-configuration.yaml

#查看安装情况
kubectl logs -n kubesphere-system $(kubectl get pod -n kubesphere-system -l app=ks-install -o jsonpath='{.items[0].metadata.name}') -f

kubernetes完整学习笔记_第46张图片

  • 解决方法:
#yaml文件中的storageClass默认为空,需要在两处添加,我的storageClass为"glusterfs"
vim  cluster-configuration.yaml

kubernetes完整学习笔记_第47张图片

#再次查看安装情况(安装成功后会有如下提示)
kubectl logs -n kubesphere-system $(kubectl get pod -n kubesphere-system -l app=ks-install -o jsonpath='{.items[0].metadata.name}') -f

kubernetes完整学习笔记_第48张图片

  • 访问 curl:http://172.16.8.124:30880/

kubernetes完整学习笔记_第49张图片

10.3.部署dashboard
wget https://oss.linuxtxc.com/deploy/yaml/kubernetes-dashboard.yaml
kubectl apply -f  kubernetes-dashboard.yaml

#查看Nodeport访问端口
kubectl get service -n kubernetes-dashboard

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uHlpixpw-1654139062282)(C:\Users\linux\AppData\Roaming\Typora\typora-user-images\image-20220526194221833.png)]

  • https://nodeIP:30081

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mPMbyF26-1654139062283)(C:\Users\linux\AppData\Roaming\Typora\typora-user-images\image-20220526194337744.png)]

#创建用户
kubectl create serviceaccount dashboard-admin -n kube-system

#用户授权
kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin

#获取token
kubectl describe secrets -n  kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')
  • 输入token后

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y4RhyYhs-1654139062284)(C:\Users\linux\AppData\Roaming\Typora\typora-user-images\image-20220526194701213.png)]

11.helm

1.1.helm安装
#GitHub下载地址
#https://github.com/helm/helm/releases
wget https://get.helm.sh/helm-v3.5.4-linux-amd64.tar.gz
tar -xf helm-v3.5.4-linux-amd64.tar.gz
mv linux-amd64/helm  /usr/local/bin/

#查看版本
helm version
1.2.helm安装harbor
#下载harbor Chart
helm repo add harbor https://helm.goharbor.io
helm fetch harbor/harbor --untar

#进入目录
cd harbor
  • 编辑values.yaml文件

你可能感兴趣的:(运维,kubernetes,容器)