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
一个 kubernetes 集群主要由控制节点(master)、工作节点(node)构成,每个节点上都会安装不同的组件。
控制节点(master):集群的控制平面,负责集群的决策。
工作节点(node):集群的数据平面,负责为容器提供运行环境。
部署网络组件的作用?
实现容器跨主机网络通信
容器接口
CNI 容器网络接口
CRI 容器运行时接口 (对接容器接口)
CSI 容器存储接口
k8s -> docker-shim/cri -> docker (有dockershim,默认能兼容docker)
k8s -> cri -> docker(支持cri) (后期需要docker去兼容对接 CRI)
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
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
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
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
#当主节点启动完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
#查看组件健康情况
kubectl get cs
vim /etc/kubernetes/manifests/kube-controller-manager.yaml (注释掉 - --port=0)
vim /etc/kubernetes/manifests/kube-scheduler.yaml (注释掉 - --port=0)
systemctl start kubelet
#再次查看
#主节点执行
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
#安装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)
#官方模板: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
(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=0)
vim /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
#启动模块(默认已经启用)
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
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* | *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 |
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
kubectl api-resources #查看k8s所有的资源以及对应的apiversion
kubectl api-versions #查看k8s所有 版本号
kubectl explain 资源类型(pod,deployment) # 查看某种资源可以配置的一级配置
kubectl explain 资源类型.属性 #查看资源的子属性
版本类标签(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 #覆盖原来的标签
kubectl describe pod nginx-pod -n web #查看pod 的详细信息
kubectl describe service nginx-svc -n web #查看service的 详细信息
kubectl describe node 192.168.3.125 #查看node的详细信息
#进入pod容器中
kubectl exec -it nginx-deployment-798444d598-87hlk -n web /bin/sh
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,根据标签过滤资源)
kubectl edit cm kubeadm-config -n kube-system #cm,configMap;编辑configMap中的配置
kubectl logs nginx-deployment-798444d598-87hlk -n web #查看pod日志
kubectl logs -f nginx-deployment-798444d598-87hlk -n web #实时查看日志
kubectl log nginx-deployment-798444d598-87hlk -c <container_name> -n web #查看pod中单个容器的日志
kubectl logs -l app=frontend -n web #返回全部标记为 app=frontend 的 pod 的合并日志
kubectl 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
kubectl autoscale deployment deployment-nginx --cpu-percent=60 --min=2 --max=10 #使用 Deployment “deployment-nginx”设定,使用默认的自动伸缩策略,指定目标CPU使用率,使其Pod数量在2到10之间。
#使用(patch)补丁修改、更新资源的字段。
kubectl patch pod rc-nginx-2-kpiqt -p '{"metadata":{"labels":{"app":"nginx-3"}}}' #修改资源配置
kubectl replace -f rc-nginx.yaml #根据yaml文件更新修改后配置资源,会停掉原来的资源,重新创建
kubectl scale rc redis --replicas=3 -n web #操作pod 的扩容和缩容
kubectl scale --replicas=2 -f redis-slave-deployment.yaml
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
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并把料清除掉
kubectl run nginx --image=nginx:1.17.1 -n web #命令使用镜像创建容器
#如果资源不存在,就创建,相当于kubectl create。
#如果资源存在,就更新,相当于kubectl patch。
kubectl apply -f nginx-pod.yaml -n web --record (--record,记录操作记录,便于回滚)
kubectl top pod/node -n dev #查看资源使用情况(需要安装metrics-server)
#将tomcat-deployment 服务的8080 端口 暴露给 tomcat-service 的service (也相当于创建service)
kubectl expose deployment tomcat-deployment --port=8080 --target-port=8080 --type=ClusterIP --name=tomcat-service -n app
#将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后的目录绝对路径不用写"/"
#kubectl certificate用来修改证书资源,可选approve/deny同意与拒绝审批。
#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
pod:k8s 最小控制单元,其中包含一个pause容器(根容器),多个user 容器,提供服务,pod中容器共享网络,存储资源
pause容器作用:可以根据它判断pod的健康状态,同时在pause容器上设置IP,可以让同一个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
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支持配置三种拉取策略:
我们一般将Pod对象从创建到终止的这段时间范围称为Pod的生命周期,它主要包含下面的过程:
钩子函数能够感知自身生命周期中的事件,并在相应的时刻到来时运行用户指定的程序代码。
kubernetes在主容器启动之后和停止之前提供了两个钩子函数:
钩子处理器支持使用下面的三种方式定义动作:
……
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"]
容器探测用于检测容器中的应用实例是否正常工作,是保障业务可用性的一种传统机制。
上面两种探针目前均支持三种探测方式:
----------------------------
readinessProbe:
exec:
command:
- cat
- /etc/hosts
initialDelaySeconds: 5
timeoutSeconds: 2
successThreshold: 3
failureThreshold: 2
periodSeconds: 5
-----------------------------
……
livenessProbe:
tcpSocket:
port: 8080
failureThreshold: 5 #检测失败5次表示未就绪
initialDelaySeconds: 60 #初始化时间
periodSeconds: 10 #检测间隔
successThreshold: 1 #检查成功为2次表示就绪
timeoutSeconds: 5 #检测失败1次表示未就绪
……
------------------------
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: #健康检查方式:[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。
重启策略:
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 #重启策略
kubernetes提供了四大类调度方式。
nodeName:用于强制约束将Pod调度到指定的name的Node节点上。这种方式,其实是直接跳过Scheduler的调度逻辑,直接将Pod调度到指定名称的节点。
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
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节点上
虽然定向调度的两种方式,使用起来非常方便,但是也有一定的问题,那就是如果没有满足条件的Node,那么Pod将不会被运行,即使在集群中还有可用的Node列表也不行,这就限制了它的使用场景。
基于上面的问题,kubernetes还提供了一种亲和性调度(Affinity)。它在nodeSelector的基础之上进行了扩展,可以通过配置的形式,实现优先选择满足条件的Node进行调度,如果没有,也可以调度到不满足条件的节点上,使得调度更加灵活。
Affinity主要分为三类:
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(软限制):
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(硬限制):
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的要求,则系统将忽略此变化。
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过程:
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过程:
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
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
Node被设置了污点之后就和Pod之间存在了一种相斥的关系,进而拒绝Pod调度进来,甚至可以将已经存在的Pod驱逐出去。
污点的格式为:key=value:effect
,key和value是污点的标签,effect描述污点的作用,支持如下三个选项:
#设置污点
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
污点是拒绝,容忍就是忽略,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 # 操作符
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 # 添加容忍的规则,这里必须和标记的污点规则相同
Deployment控制器并不直接管理Pod,而是通过管理ReplicaSet来间接管理Pod,即:Deployment管理ReplicaSet,ReplicaSet管理Pod。
Deployment的主要功能如下:
创建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
kubectl get rs -n app
kubectl rollout history deployment -n app
kubectl rollout undo deploy nginx-deployment --to-revision=1 -n app
(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
HPA可以获取每个Pod的利用率,然后和HPA中定义的指标进行对比,同时计算出需要伸缩的具体值,最后实现Pod的数量的调整。
#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
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
kubectl get pod -n kube-system
systemctl status kube-apiserver -l #或者 journalctl -u kube-apiserver
metric-server安装要满足2个条件
在master节点要能访问metrics server pod ip(kubeadm部署默认已经满足该条件,二进制部署需注意要在master节点也部署node组件)
apiserver启用聚合层支持(kubeadm默认已经启用,二进制部署需自己启用)
因为我是二进制安装的,所以在master上安装node组件就可以了
kubectl top pod -n app
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
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
需要安装metrics-server
HPA对应的pod,需要设置request资源
#使用命令行设置pod 资源限制
kubectl set resources deployment/nginx-deployment --limits=cpu=800m
DaemonSet类型的控制器可以保证集群中的每一台(或指定)节点上都运行一个副本,一般适用于日志收集、节点监控等场景
DaemonSet控制器的特点:
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
Job主要用于负责批量处理短暂的一次性任务。J可以保证指定数量的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"]
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
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表达式,用于指定任务的执行时间。
concurrencyPolicy:并发执行策略
案例
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
无状态应用:
有状态应用:
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
。
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
在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支持的两种工作模式:
开启ipvs(必须安装ipvs内核模块,否则会降级为iptables):
kubectl edit cm kube-proxy -n kube-system
#删除原来的kube-proxy pod
kubectl delete pod -l k8s-app=kube-proxy -n kube-system
##测试ipvs模块是否开启成功
ipvsadm -Ln
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: # 主机端口
Endpoint是kubernetes中的一个资源对象,存储在etcd中,用来记录一个service对应的所有Pod的访问地址,它是根据service配置文件中的selector描述产生的。
一个service由一组Pod组成,这些Pod通过Endpoints暴露出来,Endpoints是实现实际服务的端点集合。换言之,service和Pod之间的联系是通过Endpoints实现的。
#查看service 的详细信息
kubectl describe svc nginx-service -n app
spec.type的说明:
ClusterIP:默认值,它是kubernetes系统自动分配的虚拟IP,只能在集群内部访问。
NodePort:将Service通过指定的Node上的端口暴露给外部,通过此方法,就可以在集群外部访问服务。
LoadBalancer:使用外接负载均衡器完成到服务的负载分发,注意此模式需要外部云环境的支持。
ExternalName:把集群外部的服务引入集群内部,直接使用。
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
这类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的端口
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),如果不指定,会默认分配
kubectl get svc service-nodeport -n dev -o wide
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 #目标端口
集群内部访问外部数据库或者中间件一般采用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
apiVersion: v1
kind: Service
metadata:
name: mysql-214 #要与endpoints 的名称一样
namespace: app
spec:
type: ClusterIP
ports:
- port: 16303 # Service端口
protocol: TCP
targetPort : 16303
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
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
Service对集群之外暴露服务的主要方式有两种:NodePort和LoadBalancer,但是这两种方式,都有一定的缺点:
基于这种现状,kubernetes提供了Ingress资源对象,Ingress只需要一个NodePort或者一个LB就可以满足暴露多个Service的需求。
#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 ./
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
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
kubectl get ing ingress-http -n app
#查看访问ingress端口
kubectl get service -n ingress-nginx
为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 有效期
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
kubectl get service -n ingress-nginx
Volume是Pod中能够被多个容器访问的共享目录,它被定义在Pod上,然后被一个Pod里面的多个容器挂载到具体的文件目录下,kubernetes通过Volume实现同一个Pod中不同容器之间的数据共享以及数据的持久化存储。Volume的生命周期不和Pod中的单个容器的生命周期有关,当容器终止或者重启的时候,Volume中的数据也不会丢失。
kubernetes的Volume支持多种类型,比较常见的有下面的几个:
它是最基础的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: {}
kubectl get pod volume-emptydir -n dev -o wide
curl 172.16.67.8
kubectl logs -f volume-emptydir -n dev -c busybox
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
curl 172.16.34.7
HostPath虽然可以解决数据持久化的问题,但是一旦Node节点故障了,Pod如果转移到别的Node节点上,又会出现问题,此时需要准备单独的网络存储系统,比较常用的是NFS
NFS是一个网络文件存储系统,可以搭建一台NFS服务器,然后将Pod中的存储直接连接到NFS系统上,这样,无论Pod在节点上怎么转移,只要Node和NFS的对接没有问题,数据就可以成功访问。
yum install -y nfs-utils rpcbind
mkdir -pv /opt/data
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
yum -y install nfs-utils
#查看NFS挂载情况(-d:仅显示已被NFS客户端加载的目录; -e:显示NFS服务器上所有的共享目录。)
showmount -e 172.16.8.217
mount -t nfs 172.16.8.217:/opt/data /mnt
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 # 共享文件路径
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的自动回收失败。
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 # 回收策略
kubectl get pv
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc
namespace: dev
spec:
accessModes: #访问模式
- ReadWriteMany
selector: # 采用标签对PV选择
storageClassName: # 存储类别
resources: # 请求空间
requests:
storage: 5Gi
PVC的关键配置参数说明:
访客模式(accessModes):用于描述用户应用对存储资源的访问权限。
用于描述用户应用对存储资源的访问权限:
创建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
kubectl get pvc -n dev -o wide
#pvc3未绑定,是因为没有满足需求的pv
kubectl get pv
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
资源释放:
资源回收:
创建PVC后一直绑定不了PV的原因
①PVC的空间申请大小比PV的空间要大。
②PVC的storageClassName和PV的storageClassName不一致。
③PVC的accessModes和PV的accessModes不一致。
#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
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
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
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: glusterfs-pvc01
namespace: app
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 2Gi
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
(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中的内容挂载为容器内部的文件或目录
创建 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
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
apiVersion: v1
kind: ConfigMap
metadata:
name: configmap-php
namespace: web
data:
index.php: |
kubectl get cm -n web
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
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
跟configMap非常类似的对象,它主要是用于存储敏感信息,例如密码,密钥,证书等等。
Secret有三种类型:
#使用命令行 创建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
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
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
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
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
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
kubectl create secret docker-registry myregistrykey --docker-server=192.168.3.124 --docker-username=admin --docker-password=admin123 --docker-email=<your-email> --namespace=dev
apiVersion: v1
kind: Pod
metadata:
name: dev
spec:
containers:
- name: foo
image: janedoe/awesomeapp:v1
imagePullSecrets:
- name: myregistrykey
#创建一个sa 名称为admin
kubectl create serviceaccount admin -n dev
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的名称
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
#安装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
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
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"
[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]
systemctl start heketi
systemctl enable heketi
systemctl status heketi
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":[]}
[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
[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"
[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的数据卷。
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
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也会自动创建
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
kubectl exec -it mysql-5b94895868-n6xld -n app mount | grep 172
gluster volume status
#修改yaml配置
vim glusterfs-pvc.yaml
kubectl apply -f glusterfs-pvc.yaml
kubectl get pvc -n app
● 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:角色绑定,用于将角色(权限的集合)赋予给对象。
# 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可以对集群范围内的资源、跨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"。
角色绑定用来把一个角色绑定到一个目标对象上,绑定目标可以是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在整个集群级别和所有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
# 虽然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
#创建用户的私钥
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
[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授权
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
通过了前面的认证和授权之后,还需要经过准入控制通过之后,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的安全策略进行控制
#下载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/
#下载
#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
#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
#yaml文件中的storageClass默认为空,需要在两处添加,我的storageClass为"glusterfs"
vim 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
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)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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}')
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y4RhyYhs-1654139062284)(C:\Users\linux\AppData\Roaming\Typora\typora-user-images\image-20220526194701213.png)]
#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
#下载harbor Chart
helm repo add harbor https://helm.goharbor.io
helm fetch harbor/harbor --untar
#进入目录
cd harbor