k8s集群

1.k8s用途

kubernetes的本质是一组服务器集群,它可以在集群的每个节点上运行特定的程序,来对节点中的容器 进行管理。目的是实现资源管理的自动化,主要提供了如下的主要功能:

自我修复:一旦某一个容器崩溃,能够在1秒中左右迅速启动新的容器

弹性伸缩:可以根据需要,自动对集群中正在运行的容器数量进行调整

服务发现:服务可以通过自动发现的形式找到它所依赖的服务

负载均衡:如果一个服务起动了多个容器,能够自动实现请求的负载均衡

版本回退:如果发现新发布的程序版本有问题,可以立即回退到原来的版本

存储编排:可以根据容器自身的需求自动创建存储

2.k8s节点

一个kubernetes集群主要是由控制节点(master)、工作节点(node)构成,每个节点上都会安装不同的组件

1.master:集群的控制平面,负责集群的决策

ApiServer : 资源操作的唯一入口,接收用户输入的命令,提供认证、授权、API注册和发现等机制 Scheduler : 负责集群资源调度,按照预定的调度策略将Pod调度到相应的node节点上 ControllerManager : 负责维护集群的状态,比如程序部署安排、故障检测、自动扩展、滚动更新 等

Etcd :负责存储集群中各种资源对象的信息

2.node:集群的数据平面,负责为容器提供运行环境

kubelet:负责维护容器的生命周期,同时也负责Volume(CVI)和网络(CNI)的管理

Container runtime:负责镜像管理以及Pod和容器的真正运行(CRI)

kube-proxy:负责为Service提供cluster内部的服务发现和负载均衡

3.K8S 的 常用名词感念

4.k8s环境部署

k8s有多种部署方式,主流的有kubeadm minikube 二进制包

① minikube:一个用于快速搭建单节点的kubernetes工具。

●② kubeadm:一个用于快速搭建kubernetes集群的工具。

●③ 二进制包:从官网上下载每个组件的二进制包,依次去安装,此方式对于理解kubernetes组件更加有效。

本次环境搭建需要三台CentOS服务器(一主二从),然后在每台服务器中分别安装Docker(18.06.3)、kubeadm(1.18.0)、kubectl(1.18.0)和kubelet(1.18.0)。

master 192.168.83.201 node1 192.168.83.170 node2 192.168.83.180

4.1环境初始化

1.cat /etc/redhat-release #检查操作系统的版本 要求操作系统版本必须在7.5以上

所有节点都需要执行的操作:

2.#关闭火墙和关闭火墙开机启动

systemctl stop firewalld

systemctl disable firewalld

3.#做地址解析

cat /etc/hosts

192.168.83.201 master

192.168.83.170 node1

192.168.83.180 node2

4.#做时间同步

vi /etc/chorny.conf

server 192.168.83.201 iburst

server 192.168.83.170 iburst

server 192.168.83.180 iburst

5.#关闭selinux

getenforce #查看是否开启

setenforce 0 #临时关闭

sed -i 's/^SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config #永久关闭但是需要reboot

6.#禁用swap分区

systemctl mask swap.target

swapoff -a #临时关闭swap分区

sed -ri 's/.*swap.*/#&/' /etc/fstab #永久关闭分区 但是需要重启

7.将桥接的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_forward = 1

vm.swappiness = 0

EOF

加载br_netfilter模块

modprobe br_netfilter

生效 sysctl --system

8.开启ipvs

在kubernetes中service有两种代理模型,一种是基于iptables,另一种是基于ipvs的。ipvs的性能要高于iptables的,但是如果要使用它,需要手动载入ipvs模块。

●在每个节点安装ipset和ipvsadm:

yum -y install ipset ipvsadm

在所有节点执行如下脚本:

cat > /etc/sysconfig/modules/ipvs.modules <<EOF

#!/bin/bash

modprobe -- ip_vs

modprobe -- ip_vs_rr

modprobe -- ip_vs_wrr

modprobe -- ip_vs_sh

modprobe -- nf_conntrack_ipv4

EOF

授权、运行、检查是否加载:

chmod 755 /etc/sysconfig/modules/ipvs.modules && bash /etc/sysconfig/modules/ipvs.modules && lsmod | grep -e ip_vs -e nf_conntrack_ipv4

检查是否加载:

lsmod | grep -e ipvs -e nf_conntrack_ipv4

9.每个节点安装Docker、kubeadm、kubelet和kubectl

安装Docker:

wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo

yum -y install docker-ce-18.06.3.ce-3.el7

systemctl enable docker && systemctl start docker

docker version #查看docker版本

然后可以在/etc/docker/daemon.json 配置docker镜像加速器 方便拉取镜像

sudo systemctl daemon-reload

sudo systemctl restart docker

添加阿里云的YUM软件源

由于kubernetes的镜像源在国外,非常慢,这里切换成国内的阿里云镜像源

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

安装kubeadm、kubelet和kubectl

yum install -y kubelet-1.18.0 kubeadm-1.18.0 kubectl-1.18.0

为了实现Docker使用的cgroup drvier和kubelet使用的cgroup drver一致,建议修改"/etc/sysconfig/kubelet"文件的内容:

vim /etc/sysconfig/kubelet

修改 KUBELET_EXTRA_ARGS="--cgroup-driver=systemd"

KUBE_PROXY_MODE="ipvs"

systemctl enable kubelet # 设置开机自启动

部署master节点

由于默认拉取镜像地址k8s.gcr.io国内无法访问,这里需要指定阿里云镜像仓库地址

kubeadm init \

--apiserver-advertise-address=192.168.18.100 \ #master节点 ip

--image-repository registry.aliyuncs.com/google_containers \

--kubernetes-version v1.18.0 \

--service-cidr=10.96.0.0/12 \

--pod-network-cidr=10.244.0.0/16

根据提示消息,在Master节点上使用kubectl工具:

mkdir -p $HOME/.kube

sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config

sudo chown (id -u):(id -g) $HOME/.kube/config

部署k8s的Node节点

根据提示,在node节点服务器添加类似如下信息:

kubeadm join 192.168.18.100:6443 --token jv039y.bh8yetcpo6zeqfyj \

--discovery-token-ca-cert-hash sha256:3c81e535fd4f8ff1752617d7a2d56c3b23779cf9545e530828c0ff6b507e0e26

在master 节点执行生成 token 加入节点

kubeadm token create --print-join-command

10部署网络CNI插件

据提示,在Master节点上使用kubectl工具查看节点状态:

kubectl get nodes

kubernetes支持多种网络插件,比如flannel、calico、canal等,

我这是是提前下载好的flannel.yaml文件

直接执行 kubectl apply -f flannel.yaml

kubectl命令自动补全设置

yum install -y bash-completion

source /usr/share/bash-completion/bash_completion

source <(kubectl completion bash)

echo "source <(kubectl completion bash)" >> ~/.bashrc

vim /root/.bashrc

source /usr/share/bash-completion/bash_completion

source <(kubectl completion bash)

5.k8s资源管理

在Kubernetes中,所有的内容都抽象为资源,用户需要通过操作资源来管理Kubernetes。

Kubernetes的本质就是一个集群系统,用户可以在集群中部署各种服务。所谓的部署服务,其实就是在Kubernetes集群中运行一个个的容器,并将指定的程序跑在容器中。

●Kubernetes的最小管理单元是Pod而不是容器,所以只能将容器放在Pod中,而Kubernetes一般也不会直接管理Pod,而是通过Pod控制器来管理Pod的。

●Pod提供服务之后,就需要考虑如何访问Pod中的服务,Kubernetes提供了Service资源实现这个功能。

●当然,如果Pod中程序的数据需要持久化,Kubernetes还提供了各种存储系统

5.1资源管理方式

k8s资源管理方式有三种:

命令式对象管理:直接使用命令去操作kubernetes的资源。

kubectl run nginx-pod --image=nginx:1.17.1 --port=80 #直接创建一个pod并指定运行nginx容器

命令式对象配置:通过命令配置和配置文件去操作kubernetes的资源。

kubectl create/patch -f nginx-pod.yaml

声明式对象配置:通过apply命令和配置文件去操作kubernetes的资源。

kubectl apply -f nginx-pod.yaml

5.2基本命令式例

kubectl version #显示集群版本信息

kubectl cluster-info #显示集群信息

kubectl create deployment web --image=nginx:latest #创建一个web控制器

更高k8s版本可以通过 --replicas 2 来指定控制器中的pod数量

kubectl get deployments.apps #查看控制器信息

kubectl explanin deployment # 查看资源帮助

kubectl explain deployment.spec #查看控制器参数帮助

kubectl edit deployments.apps web -o yaml 以yaml的形式输出deployment的信息

kubectl edit deployment.apps web 修改yaml

#端口暴露:先启动pod 然后再暴露端口

kubectl run testpod --image reg.timinglee.org/pod/nginx

kubectl expose pod testpod --port 80 --target-port 80 通过暴露端口可以实现对外访问

kubectl logs pods/testpod 查看这个端口的日志

kubectl run -it testpod --image busybox #运行交互pod

kubectl run nginx --image nginx # 运行非交互pod

kubectl attach pods/testpod -it # 进入已经运行的容器 且容器有交互环境

5.3高级命令示例

使用命令生成yaml 模板文件

kubectl create deploment --image nginx webcluster --dry-run=client -o yaml > webcluster.yaml

kubcectl apply -f webcluster.yaml

kubectl delete -f webcluster.yaml

###控制器会通过pod的标签去弹性伸缩pod数量

如图pod labels为web

kubectl label pods web-6ddfddb795-62jn6 app=lee --overwrite #改一个pod标签为

由于指定了replicas此时deploment控制器会发现 少一个副本数量

于是会添加一个pods服务于web

6.k8s中的pod

k8s最小控制单元pod

一个pod代表着集群中运行的一个进程,每一个pod都有唯一的一个ip

一个pod类似一个豌豆荚,包含一个或多个容器

多个容器共享ipc,Network和UTC namesoace

6.1创建自主式pod(不推荐)
6.2利用控制器管理pod(推荐)
6.2.1 扩缩容

kubectl create deploment web ---image nginx

#给web扩容

kubectl scale deployment web --replicas 2

给web缩容

6.2.2应用版本更新
6.3利用yaml文件部署应用

kubectl explain pod.spec.containers #查看资源帮助

6.4 pod的生命周期

Init容器: 主要功能在启动pod前先执行init容器 作为一个判断条件 当条件满足时候才能启动pod

或者作为运行pod环境里需要的一些东西

(通俗易懂的讲就是说initpod执行起来才会执行pod容器

init容器的功能

执行该pod先执行initContainers 等该模块符合条件了 才会执行containers启动这个pod

6.5pod的探针

检测pod运行情况是怎么样的

7.k8s中控制器

控制器也是管理pod的一种手段

  • 自主式pod:pod退出或意外关闭后不会被重新创建

  • 控制器管理的 Pod:在控制器的生命周期里,始终要维持 Pod 的副本数目

Pod控制器是管理pod的中间层,使用Pod控制器之后,只需要告诉Pod控制器,想要多少个什么样的Pod就可以了,它会创建出满足条件的Pod并确保每一个Pod资源处于用户期望的目标状态。如果Pod资源在运行中出现故障,它会基于指定策略重新编排Pod

当建立控制器后,会把期望值写入etcd,k8s中的apiserver检索etcd中我们保存的期望状态,并对比pod的当前状态,如果出现差异代码自驱动立即恢复

控制器名称 控制器用途
Replication Controller 比较原始的pod控制器,已经被废弃,由ReplicaSet替代
ReplicaSet ReplicaSet 确保任何时间都有指定数量的 Pod 副本在运行
Deployment 一个 Deployment 为 PodReplicaSet 提供声明式的更新能力
DaemonSet DaemonSet 确保全指定节点上运行一个 Pod 的副本
StatefulSet StatefulSet 是用来管理有状态应用的工作负载 API 对象。
Job 执行批处理任务,仅执行一次任务,保证任务的一个或多个Pod成功结束
CronJob Cron Job 创建基于时间调度的 Jobs。
HPA全称Horizontal Pod Autoscaler 根据资源利用率自动调整service中Pod数量,实现Pod水平自动缩放

无状态pod 每重启一次 都换一个id

有状态pod 被记录着 始终是保持一个id

7.1replicaset控制器
  • ReplicaSet 是下一代的 Replication Controller,官方推荐使用ReplicaSet

  • ReplicaSet和Replication Controller的唯一区别是选择器的支持,ReplicaSet支持新的基于集合的选择器需求

  • ReplicaSet 确保任何时间都有指定数量的 Pod 副本在运行

  • 虽然 ReplicaSets 可以独立使用,但今天它主要被Deployments 用作协调 Pod 创建、删除和更新的机制

参数名称 字段类型 参数说明
spec Object 详细定义对象,固定值就写Spec
spec.replicas integer 指定维护pod数量
spec.selector Object Selector是对pod的标签查询,与pod数量匹配
spec.selector.matchLabels string 指定Selector查询标签的名称和值,以key:value方式指定
spec.template Object 指定对pod的描述信息,比如lab标签,运行容器的信息等
spec.template.metadata Object 指定pod属性
spec.template.metadata.labels string 指定pod标签
spec.template.spec Object 详细定义对象
spec.template.spec.containers list Spec对象的容器列表定义
spec.template.spec.containers.name string 指定容器名称
spec.template.spec.containers.image string 指定容器镜像

replicaset 时刻保持pod按照replicas在运行

实质是deployment 的一个分支版本 是通过labels去控制pod数量

#生成yml文件

root@k8s-master \~\]# kubectl create**deployment replicaset** --image myapp:v1 --dry-run=client -o yaml \> replicaset.yml \[root@k8s-master \~\]# vim replicaset.yml apiVersion: apps/v1 **kind: ReplicaSet #yaml文件创建出来要更改此处类型** metadata: name: replicaset #指定pod名称,一定小写,如果出现大写报错 spec: replicas: 2 #指定维护pod数量为2 selector: #指定检测匹配方式 matchLabels: #指定匹配方式为匹配标签 app: myapp #指定匹配的标签为app=myapp template: #模板,当副本数量不足时,会根据下面的模板创建pod副本 metadata: labels: app: myapp spec: containers: - image: myapp:v1 name: myapp \[root@k8s-master \~\]# kubectl apply -f replicaset.yml replicaset.apps/replicaset created #replicaset是通过标签匹配pod \[root@k8s-master \~\]# kubectl label pod replicaset-l4xnr app=timinglee --overwrite pod/replicaset-l4xnr labeled \[root@k8s-master \~\]# kubectl get pods --show-labels NAME READY STATUS RESTARTS AGE LABELS replicaset-gd5fh 1/1 Running 0 2s app=myapp #新开启的pod replicaset-l4xnr 1/1 Running 0 3m19s app=timinglee replicaset-t2s5p 1/1 Running 0 3m19s app=myapp #恢复标签后 \[root@k8s2 pod\]# kubectl label pod replicaset-example-q2sq9 app- \[root@k8s2 pod\]# kubectl get pod --show-labels NAME READY STATUS RESTARTS AGE LABELS replicaset-example-q2sq9 1/1 Running 0 3m14s app=nginx replicaset-example-th24v 1/1 Running 0 3m14s app=nginx replicaset-example-w7zpw 1/1 Running 0 3m14s app=nginx ##### 7.2deploment控制器 * 为了更好的解决服务编排的问题,kubernetes在V1.2版本开始,引入了Deployment控制器。 * Deployment控制器并不直接管理pod,而是通过管理ReplicaSet来间接管理Pod * Deployment管理ReplicaSet,ReplicaSet管理Pod * Deployment 为 Pod 和 ReplicaSet 提供了一个申明式的定义方法 * 在Deployment中ReplicaSet相当于一个版本 * **典型的应用场景:** * 用来创建Pod和ReplicaSet * 滚动更新和回滚 * 扩容和缩容 * 暂停与恢复 例子: ###### 7.2.1版本更新 \[root@k8s-master \~\]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES deployment-5d886954d4-2ckqw 1/1 Running 0 2m40s 10.244.2.14 k8s-node2 \ \ deployment-5d886954d4-m8gpd 1/1 Running 0 2m40s 10.244.1.17 k8s-node1 \ \ deployment-5d886954d4-s7pws 1/1 Running 0 2m40s 10.244.1.16 k8s-node1 \ \ deployment-5d886954d4-wqnvv 1/1 Running 0 2m40s 10.244.2.15 k8s-node2 \ \ #pod运行容器版本为v1 \[root@k8s-master \~\]# curl 10.244.2.14 Hello MyApp \| Version: v1 \| \Pod Name\ \[root@k8s-master \~\]# kubectl describe deployments.apps deployment Name: deployment Namespace: default CreationTimestamp: Sun, 01 Sep 2024 23:19:10 +0800 Labels: \ Annotations: deployment.kubernetes.io/revision: 1 Selector: app=myapp Replicas: 4 desired \| 4 updated \| 4 total \| 4 available \| 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 25% max unavailable, 25% max surge #默认每次更新25% #更新容器运行版本 \[root@k8s-master \~\]# vim deployment.yml apiVersion: apps/v1 kind: Deployment metadata: name: deployment spec: replicas: 4 selector: matchLabels: app: myapp template: metadata: labels: app: myapp spec: containers: - image: myapp:v2 #更新为版本2 name: myapp \[root@k8s2 pod\]# kubectl apply -f deployment-example.yaml #更新过程 \[root@k8s-master \~\]# kubectl get pods -w NAME READY STATUS RESTARTS AGE deployment-5d886954d4-8kb28 1/1 Running 0 48s deployment-5d886954d4-8s4h8 1/1 Running 0 49s deployment-5d886954d4-rclkp 1/1 Running 0 50s deployment-5d886954d4-tt2hz 1/1 Running 0 50s deployment-7f4786db9c-g796x 0/1 Pending 0 0s deployment-7f4786db9c-g796x 0/1 Pending 0 0s deployment-5d886954d4-rclkp 1/1 Terminating 0 64s deployment-7f4786db9c-mk6ts 0/1 Pending 0 0s deployment-7f4786db9c-g796x 0/1 ContainerCreating 0 0s deployment-7f4786db9c-mk6ts 0/1 Pending 0 0s deployment-7f4786db9c-mk6ts 0/1 ContainerCreating 0 0s deployment-5d886954d4-rclkp 0/1 Terminating 0 65s deployment-7f4786db9c-mk6ts 1/1 Running 0 2s deployment-5d886954d4-tt2hz 1/1 Terminating 0 66s deployment-7f4786db9c-585dg 0/1 Pending 0 0s deployment-7f4786db9c-585dg 0/1 Pending 0 0s deployment-7f4786db9c-585dg 0/1 ContainerCreating 0 0s deployment-7f4786db9c-g796x 1/1 Running 0 2s deployment-5d886954d4-8s4h8 1/1 Terminating 0 65s deployment-7f4786db9c-wxsdc 0/1 Pending 0 0s deployment-5d886954d4-rclkp 0/1 Terminating 0 66s deployment-7f4786db9c-wxsdc 0/1 Pending 0 0s deployment-5d886954d4-rclkp 0/1 Terminating 0 66s deployment-7f4786db9c-wxsdc 0/1 ContainerCreating 0 0s deployment-5d886954d4-rclkp 0/1 Terminating 0 66s deployment-5d886954d4-tt2hz 0/1 Terminating 0 66s deployment-5d886954d4-8s4h8 0/1 Terminating 0 65s deployment-7f4786db9c-wxsdc 1/1 Running 0 1s deployment-5d886954d4-8kb28 1/1 Terminating 0 65s deployment-5d886954d4-tt2hz 0/1 Terminating 0 67s deployment-5d886954d4-tt2hz 0/1 Terminating 0 67s deployment-5d886954d4-tt2hz 0/1 Terminating 0 67s deployment-5d886954d4-8s4h8 0/1 Terminating 0 66s deployment-5d886954d4-8s4h8 0/1 Terminating 0 66s deployment-5d886954d4-8s4h8 0/1 Terminating 0 66s deployment-7f4786db9c-585dg 1/1 Running 0 1s deployment-5d886954d4-8kb28 0/1 Terminating 0 65s deployment-5d886954d4-8kb28 0/1 Terminating 0 66s deployment-5d886954d4-8kb28 0/1 Terminating 0 66s deployment-5d886954d4-8kb28 0/1 Terminating 0 66s #测试更新效果 \[root@k8s-master \~\]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES deployment-7f4786db9c-967fk 1/1 Running 0 10s 10.244.1.26 k8s-node1 \ \ deployment-7f4786db9c-cvb9k 1/1 Running 0 10s 10.244.2.24 k8s-node2 \ \ deployment-7f4786db9c-kgss4 1/1 Running 0 9s 10.244.1.27 k8s-node1 \ \ deployment-7f4786db9c-qts8c 1/1 Running 0 9s 10.244.2.25 k8s-node2 \ \ \[root@k8s-master \~\]# curl 10.244.1.26 Hello MyApp \| Version: v2 \| \Pod Name\ ###### 7.2.2版本回滚 \[root@k8s-master \~\]# vim deployment.yml apiVersion: apps/v1 kind: Deployment metadata: name: deployment spec: replicas: 4 selector: matchLabels: app: myapp template: metadata: labels: app: myapp spec: containers: - image: myapp:v1 #回滚到之前版本 name: myapp \[root@k8s-master \~\]# kubectl apply -f deployment.yml deployment.apps/deployment configured #测试回滚效果 \[root@k8s-master \~\]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES deployment-5d886954d4-dr74h 1/1 Running 0 8s 10.244.2.26 k8s-node2 \ \ deployment-5d886954d4-thpf9 1/1 Running 0 7s 10.244.1.29 k8s-node1 \ \ deployment-5d886954d4-vmwl9 1/1 Running 0 8s 10.244.1.28 k8s-node1 \ \ deployment-5d886954d4-wprpd 1/1 Running 0 6s 10.244.2.27 k8s-node2 \ \ \[root@k8s-master \~\]# curl 10.244.2.26 Hello MyApp \| Version: v1 \| \Pod Name\ ###### 7.2.3滚动更新策略 \[root@k8s-master \~\]# vim deployment.yml apiVersion: apps/v1 kind: Deployment metadata: name: deployment spec: minReadySeconds: 5 #最小就绪时间,指定pod每隔多久更新一次 replicas: 4 strategy: #指定更新策略 rollingUpdate: maxSurge: 1 #允许比定义的pod多一个pod 多一个pod更新一个pod 直至更新完毕 maxUnavailable: 0 #定义了四个pod 更新的时候4个pod必须同时running中 selector: matchLabels: app: myapp template: metadata: labels: app: myapp spec: containers: - image: myapp:v1 name: myapp \[root@k8s2 pod\]# kubectl apply -f deployment-example.yaml ###### 7.2.4暂停及恢复 在实际生产环境中我们做的变更可能不止一处,当修改了一处后,如果执行变更就直接触发了 我们期望的触发时当我们把所有修改都搞定后一次触发 暂停,避免触发不必要的线上更新 kubectl rollout pause deployment deployment-example #暂停更新 kubectl rollout resume deployment deployment-example #恢复更新后触发更新的内容 kubectl rollout history deployment deployment-example #查看更新的历史 ##### 7.3daemonsent控制器 **DaemonSet 确保全部(或者某些)节点上运行一个 Pod 的副本。**当有节点加入集群时, 也会为他们新增一个 Pod ,当有节点从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod DaemonSet 的典型用法: * 在每个节点上运行集群存储 DaemonSet,例如 glusterd、ceph。 * 在每个节点上运行日志收集 DaemonSet,例如 fluentd、logstash。 * 在每个节点上运行监控 DaemonSet,例如 Prometheus Node Exporter、zabbix agent等 * 一个简单的用法是在所有的节点上都启动一个 DaemonSet,将被作为每种类型的 daemon 使用 * 一个稍微复杂的用法是单独对每种 daemon 类型使用多个 DaemonSet,但具有不同的标志, 并且对不同硬件类型具有不同的内存、CPU 要求 ![](https://i-blog.csdnimg.cn/direct/6bb2e57bd53342fe8c2fffcabc90630f.png) 查看master节点信息 他有污点是NoSchedule 所以不给他调度服务 ![](https://i-blog.csdnimg.cn/direct/c5ad125b59574f0681dd1349219af8be.png) spec: tolerations: #对于污点节点的容忍 - effect: NoSchedule operator: Exists #强容忍 有没有污点都能容忍 通过添加 template下的spec模块下的tolerations模块 能实现污点的容忍 所以 能给master节点调度到pod ![](https://i-blog.csdnimg.cn/direct/f63e7e8f1ab94bdc843fbf0e9c86c7c8.png) ##### 7.4job控制器 Job,主要用于负责批量处理(一次要处理指定数量任务)短暂的一次性(每个任务仅运行一次就结束)任务 Job特点如下: * 当Job创建的pod执行成功结束时,Job将记录成功结束的pod数量 * 当成功结束的pod达到指定的数量时,Job将完成执行 kubectl create job t-job --images perl:5.34.0 --dry-run=client -o yaml \> job.yaml apiVersion: batch/v1 kind: Job metadata: name: pi spec: completions: 6 #一共完成任务数为6 parallelism: 2 #每次并行完成2个 template: spec: containers: - name: pi image: perl:5.34.0 command: \["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"\] 计算Π的后2000位 restartPolicy: Never #关闭后不自动重启 backoffLimit: 4 #运行失败后尝试4重新运行 关于重启策略设置的说明: * 如果指定为OnFailure,则job会在pod出现故障时重启容器 而不是创建pod,failed次数不变 * 如果指定为Never,则job会在pod出现故障时创建新的pod 并且故障pod不会消失,也不会重启,failed次数加1 * 如果指定为Always的话,就意味着一直重启,意味着job任务会重复去执行了 \[root@k8s2 pod\]# kubectl apply -f job.yml ##### 7.5cronjob控制器 * Cron Job 创建基于时间调度的 Jobs。 * CronJob控制器以Job控制器资源为其管控对象,并借助它管理pod资源对象, * CronJob可以以类似于Linux操作系统的周期性任务作业计划的方式控制其运行时间点及重复运行的方式。 * CronJob可以在特定的时间点(反复的)去运行job任务 kubectl create cronjob cronjob --image reg.timinglee.org/pod/busyboxplus --schedule "\*/1 \* \* \* \*" --dry-run=client -o yaml \> cronjob.yaml ![](https://i-blog.csdnimg.cn/direct/12192c7bc4884995b6e47d2f3f868fa9.png) command 为动作 通过查看日志可以看到执行是否成功 ![](https://i-blog.csdnimg.cn/direct/8087233021d64d189b86a969a93b3406.png) ### 8.k8s中的微服务 service是由kube-proxy组件和iptables共同实现的 但是宿主机有大量的pod的话 需要有很多iptables规则去不断的刷新 造成cpu资源的浪费 所以在这里 我们需要设置IPVS模式 1.ipvs配置方式: 所有节点 yum install ipvsadm -y 2.master节点: \[root@k8s-master \~\]# kubectl -n kube-system edit cm kube-proxy metricsBindAddress: "" mode: "ipvs" #设置kube-proxy使用ipvs模式 nftables: 3.重启pod,在pod运行时配置文件中采用默认配置,当改变配置文件后已经运行的pod状态不会变化,所以要重启pod \[root@k8s-master \~\]# kubectl -n kube-system get pods \| awk '/kube-proxy/{system("kubectl -n kube-system delete pods "$1)}' 用控制器来完成集群的工作负载,那么应用如何暴漏出去?需要通过微服务暴漏出去后才能被访问 * Service是一组提供相同服务的Pod对外开放的接口。 * 借助Service,应用可以实现服务发现和负载均衡。 * service默认只支持4层负载均衡能力,没有7层功能。(可以通过Ingress实现) | 微服务类型 | 作用描述 | |--------------|----------------------------------------------------------------------------------| | ClusterIP | 默认值,k8s系统给service自动分配的虚拟IP,只能在集群内部访问 | | NodePort | 将Service通过指定的Node上的端口暴露给外部,访问任意一个NodeIP:nodePort都将路由到ClusterIP | | LoadBalancer | 在NodePort的基础上,借助cloud provider创建一个外部的负载均衡器,并将请求转发到 NodeIP:NodePort,此模式只能在云服务器上使用 | | ExternalName | 将服务通过 DNS CNAME 记录方式转发到指定的域名(通过 spec.externlName 设定 | ###### 8.1 clusterip 想要访问pod里的服务的时候 先访问的是service的域名 然后通过ipvs策略转发到后面的pod 系统默认分配的虚拟ip 只允许在集群内部访问 ![](https://i-blog.csdnimg.cn/direct/c123563f315f4c8eac13ee63863fbaf2.png) 访问成功 特殊模式headless无头服务: 直接去访问pod 不经过访问svc 直接访问pod ip ![](https://i-blog.csdnimg.cn/direct/b37380e3cad140fda326448117eed1a6.png) ###### 8.2 NodePort nodeport 本质 通过ipvs暴露端口 给开启的pod里的服务提供一个对外访问的端口 ![](https://i-blog.csdnimg.cn/direct/4762c317b61847579fe27ac7f9a63f9e.png) 修改spec 下的type ![](https://i-blog.csdnimg.cn/direct/bcbac7a92cc945b59f8a5244758e8ed0.png) 利用别的服务器进行访问测试 harbor服务器:![](https://i-blog.csdnimg.cn/direct/1698fe0efc7b4022b646e1e697c4c023.png) ![](https://i-blog.csdnimg.cn/direct/fa6581f8d2e341579429b2c14f34c806.png) 也可以通过修改指定端口 进行访问 ![](https://i-blog.csdnimg.cn/direct/4a74449cff60401da7871b73500446dc.png) 访问成功 **nodeport默认端口是30000-32767,超出会报错 (如果要范围以外的 需要更改配置文件中的特殊设定)** **vim /etc/kubernetes/manifests/kube-apiserver.yaml** **- --service-node-port-range=30000-40000** 添加"--service-node-port-range=" 参数,端口范围可以自定义 修改后api-server会自动重启,等apiserver正常启动后才能操作集群 集群重启自动完成在修改完参数后全程不需要人为干预 ###### 8.3LoadBalancer (metalLB) 云平台会为我们分配vip并实现访问,如果是裸金属主机那么需要metallb来实现ip的分配 访问方式: ![](https://i-blog.csdnimg.cn/direct/4ab9e98e40514056a692dd8b8f05bcd7.png) ![](https://i-blog.csdnimg.cn/direct/f6dccd64af8a45b4bf4ff63ceff44da1.png) metalLB可以为 LoadBalancer 分配vip 服务器部署metalLB : 首先将master设置为ipvs模式 ![](https://i-blog.csdnimg.cn/direct/d3810e2e78ce44689cf1108e96ae6bdb.png) 2.下载部署文件 wget https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml 3.将下载下来的镜像 打上标签push到本地k8sharbor仓库 ![](https://i-blog.csdnimg.cn/direct/d7ea238964e4471487b09e8a481c81fe.png) ![](https://i-blog.csdnimg.cn/direct/004ad49b9af3499ea1b86bed6cbf5d23.png) 4. 修改metallb-native.yaml中的image 指定镜像位置 ![](https://i-blog.csdnimg.cn/direct/7811e78dfe144c65bfeea18017a913dd.png) ![](https://i-blog.csdnimg.cn/direct/fac181e9d06749678af4c62e255bf7dd.png) kubectl apply -f metallb-native.yaml #部署服务 vi configmap.yaml #设置地址池 ![](https://i-blog.csdnimg.cn/direct/a510625344384646aa6fc1c0da36240f.png) ![](https://i-blog.csdnimg.cn/direct/516ade1e0b5e46c48ca9a0366ec0dcc4.png) 查看服务loadbalancer 已经有metalLB分配的ip 外部可以通过访问这个ip 访问pod内部容器 ![](https://i-blog.csdnimg.cn/direct/3b37f807f824404db982315a1b408795.png) 访问成功 ###### 8.4ExternalName 将服务通过DNS CNAME记录方式转发到指定的域名 * 开启services后,不会被分配IP,而是用dns解析CNAME固定域名来解决ip变化问题 * 一般应用于外部业务和pod沟通或外部业务迁移到pod内时 * 在应用向集群迁移过程中,externalname在过度阶段就可以起作用了。 * 集群外的资源迁移到集群时,在迁移的过程中ip可能会变化,但是域名+dns解析能完美解决此问题 #首先查看k8s集群dns为10.96.0.10 ![](https://i-blog.csdnimg.cn/direct/4aa442d247dd41ee93c0599f7917cbef.png) 修改yaml文件指定service类型 已经访问的域名 ![](https://i-blog.csdnimg.cn/direct/a84f7872912a4fc281c86814ae67da78.png) 如下图为通过dns解析指向www.baidu.com ![](https://i-blog.csdnimg.cn/direct/191d9a58a29f4b2e813f08c3813e0409.png) #### 8.5 ingress * 一种全局的、为了代理不同后端 Service 而设置的负载均衡服务,**支持7层** * Ingress由两部分组成:Ingress controller和Ingress服务 * Ingress Controller 会根据你定义的 Ingress 对象,提供对应的代理能力。 * 业界常用的各种反向代理项目,比如 Nginx、HAProxy、Envoy、Traefik 等,都已经为Kubernetes 专门维护了对应的 Ingress Controller。 ingress相当于一个调度器 把请求调度到合适的service 或pod ingress部署: 1.用yaml文件的方式部署 首先在ingress官网下载deploy.yaml到本地服务器 2.![](https://i-blog.csdnimg.cn/direct/7fb40f16ba214b3fb557eae4bcac0fda.png) ![](https://i-blog.csdnimg.cn/direct/49f8c0f4c6884641a176cdaa34a2c221.png) 将这俩个镜像打上标签 上传到本地的harbor仓库 3上传完成后 修改 deploy.yaml 指定拉取位置本地harbor仓库 ![](https://i-blog.csdnimg.cn/direct/18fbba034bed4a15887da384e53b7453.png) ![](https://i-blog.csdnimg.cn/direct/4c211235c14042a88086b823643b6f66.png) ![](https://i-blog.csdnimg.cn/direct/959c8c34c611410d89f1f7368886f3a7.png) 4.kubectl apply -f deploy.ment ![](https://i-blog.csdnimg.cn/direct/f128a69f8ae0425ea4021abd68a793eb.png) 查看状态已经部署完成. ###### 8.5.1 基于访问路径的发布 首先创建俩个服务不同的pod kubectl create deployment myappv1 --image reg.timinglee.org/pod/myapp:v1 --dry-run=client -o yaml \> myappv1.yaml kubectl create deployment myappv2 --image reg.timinglee.org/pod/myapp:v2 --dry-run=client -o yaml \> myappv2.yaml kubectl expose deployment myappv1 --port 80 --target-port 80 --dry-run=client -o yaml \>\> myappv1.yaml kubectl expose deployemnt myappv2 --port 80 --target-port 80 --dry-run=client -o yaml \>\> myappv2.yaml ![](https://i-blog.csdnimg.cn/direct/c5da8178a78941f7803c64de9343b4a3.png) service 已开启 然后开始简历ingress的yaml kubectl create ingress myappv1 --class nginx --rule='/=myappv1:80' --dry-run=client -o yaml \> ingress1.yaml ![](https://i-blog.csdnimg.cn/direct/1c7ba712ca0f47478137202ca1470a7e.png) 查看ingress svc的模式为loadbalance metallb分配的IP为 172.25.254.50 **kubectl -n ingress-nginx edit svc ingress-nginx-controller(修改微服务的方式** ![](https://i-blog.csdnimg.cn/direct/b2e18943470448db9b50e28574755fb9.png) 然后测试一下 在/etc/hosts下 echo 172.25.254.50 www.timinglee.org \>\> /etc/hosts \[root@reg \~\]# curl www.timinglee.org/v1 Hello MyApp \| Version: v1 \| \Pod Name\ \[root@reg \~\]# curl www.timinglee.org/v2 Hello MyApp \| Version: v2 \| \Pod Name\ #nginx.ingress.kubernetes.io/rewrite-target: / 的功能实现 \[root@reg \~\]# curl www.timinglee.org/v2/aaaa Hello MyApp \| Version: v2 \| \Pod Name\ 成功访问 ###### 8.5.2 基于域名的访问 cat ingress3.yaml ![](https://i-blog.csdnimg.cn/direct/ce217914321643b193e9736205eba5f7.png) 在/etc/hosts下做本地解析 172.25.254.50 myappv1.timinglee.org myappv2.timinglee.org 然后查看信息进行访问验证 ![](https://i-blog.csdnimg.cn/direct/4a8c5f0cc52d47fb944a1561d02cbbe8.png) ###### 8.5.3简历tls认证(基于https进行访问控制) 1.生成证书和key openssl req -newkey rsa:2048 -nodes -keyout tls.key -x509 -days 365 -subj "/CN=nginxsvc/O=nginxsvc" -out tls.crt #建立加密资源类型secret \[root@k8s-master app\]# kubectl create secret tls web-tls-secret --key tls.key --cert tls.crt secret/web-tls-secret created \[root@k8s-master app\]# kubectl get secrets NAME TYPE DATA AGE web-tls-secret kubernetes.io/tls 2 6s vi ingress.yaml ![](https://i-blog.csdnimg.cn/direct/4605e096857a4341b6b2f80f96c3601f.png) 然后再/etc/hosts 172.25.254.50 myapp-tls.timinglee.org 访问成功 ![](https://i-blog.csdnimg.cn/direct/ab072ccb06354816a23b5648c5a85511.png) ###### 8.5.4 auth认证(基于https访问的时候需要密码验证) \[root@k8s-master app\]# dnf install httpd-tools -y \[root@k8s-master app\]# htpasswd -cm auth lee New password: Re-type new password: Adding password for user lee \[root@k8s-master app\]# cat auth lee:$apr1$BohBRkkI$hZzRDfpdtNzue98bFgcU10 kubectl create secret generic auth-web --from-file auth #建立认证类型资源 root@k8s-master app\]# kubectl describe secrets auth-web Name: auth-web Namespace: default Labels: \ Annotations: \ Type: Opaque Data ==== auth: 42 bytes #建立ingress4基于用户认证的yaml文件 \[root@k8s-master app\]# vim ingress4.yml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: nginx.ingress.kubernetes.io/auth-type: basic nginx.ingress.kubernetes.io/auth-secret: auth-web nginx.ingress.kubernetes.io/auth-realm: "Please input username and password" name: ingress4 spec: tls: - hosts: - myapp-tls.timinglee.org secretName: web-tls-secret ingressClassName: nginx rules: - host: myapp-tls.timinglee.org http: paths: - backend: service: name: myapp-v1 port: number: 80 path: / pathType: Prefix #建立ingress4 \[root@k8s-master app\]# kubectl apply -f ingress4.yml ingress.networking.k8s.io/ingress4 created \[root@k8s-master app\]# kubectl describe ingress ingress4 Name: ingress4 Labels: \ Namespace: default Address: Ingress Class: nginx Default backend: \ TLS: web-tls-secret terminates myapp-tls.timinglee.org Rules: Host Path Backends ---- ---- -------- myapp-tls.timinglee.org / myapp-v1:80 (10.244.2.31:80) Annotations: nginx.ingress.kubernetes.io/auth-realm: Please input username and password nginx.ingress.kubernetes.io/auth-secret: auth-web nginx.ingress.kubernetes.io/auth-type: basic Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Sync 14s nginx-ingress-controller Scheduled for sync #测试: \[root@reg \~\]# curl -k https://myapp-tls.timinglee.org Hello MyApp \| Version: v1 \| \Pod Name\ \[root@reg \~\]# vim /etc/hosts \^C \[root@reg \~\]# curl -k https://myapp-tls.timinglee.org \ \\401 Authorization Required\\ \ \\401 Authorization Required\\ \\nginx\ \ \ ###### 8.5.5rewrite重定向 #### 8.6金丝雀发布 金丝雀发布(Canary Release)也称为灰度发布,是一种软件发布策略。 主要目的是在将新版本的软件全面推广到生产环境之前,先在一小部分用户或服务器上进行测试和验证,以降低因新版本引入重大问题而对整个系统造成的影响。 是一种Pod的发布方式。金丝雀发布采取先添加、再删除的方式,保证Pod的总量不低于期望值。并且在更新部分Pod后,暂停更新,当确认新Pod版本运行正常后再进行其他版本的Pod的更新。 三种发布方式 :header cookie weight ##### 8.6.1基于包头(header)的:按照键值去访问 效果 :首先我们创建俩个ingress 分别用作不同的版本 v1: ![](https://i-blog.csdnimg.cn/direct/dea15094dcac4980bceaa9942f763ae8.png) ![](https://i-blog.csdnimg.cn/direct/eec08331ed89478ca55b55aeeb4d36cd.png) v2(基于header的ingress) ![](https://i-blog.csdnimg.cn/direct/935323a3325e498d9d34cc45bde9860b.png) ![](https://i-blog.csdnimg.cn/direct/691b5986d9504a4b8a88353f914e21f0.png) ![](https://i-blog.csdnimg.cn/direct/39235561d37340aca48e3f3b911a1cbf.png) 带header的就是更新过的版本 ##### 8.6.2基于权重的灰度发布 * 通过Annotaion拓展 * 创建灰度ingress,配置灰度权重以及总权重 * 灰度流量验证完毕后,切换正式ingress到新版本 \[root@k8s-master app\]# vim ingress8.yml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: nginx.ingress.kubernetes.io/canary: "true" nginx.ingress.kubernetes.io/canary-weight: "10" #更改权重值 nginx.ingress.kubernetes.io/canary-weight-total: "100" name: myapp-v2-ingress spec: ingressClassName: nginx rules: - host: myapp.timinglee.org http: paths: - backend: service: name: myapp-v2 port: number: 80 path: / pathType: Prefix \[root@k8s-master app\]# kubectl apply -f ingress8.yml ingress.networking.k8s.io/myapp-v2-ingress created #测试: \[root@reg \~\]# vim check_ingress.sh #!/bin/bash v1=0 v2=0 for (( i=0; i\<100; i++)) do response=\`curl -s myapp.timinglee.org \|grep -c v1\` v1=\`expr $v1 + $response\` v2=\`expr $v2 + 1 - $response\` done echo "v1:$v1, v2:$v2" \[root@reg \~\]# sh check_ingress.sh v1:90, v2:10 #更改完毕权重后继续测试可观察变化 #### 9.k8s中的存储 ##### 9.1configmap pod中的镜像不一定在每个生产环境都适用 如果通过docker build -t构建的话也不一定能够适用 所以引入 configmap 功能: * configMap用于保存配置数据,以键值对形式存储。 * configMap 资源提供了向 Pod 注入配置数据的方法。 * 镜像和配置文件解耦,以便实现镜像的可移植性和可复用性。 * etcd限制了文件大小不能超过1M 使用场景: * 填充环境变量的值 * 设置容器内的命令行参数 * 填充卷的配置文件 四种创建方式: 1.通过字面值创建 kubectl create configmap userlist --from-literal name=lee --from-literal age=20 2.通过文件创建 kubectl create cm host --from-file /etc/resolv.conf 3.通过目录创建 kubectl create cm host1 --from-file /root/configmap/test/ 4.通过yaml创建 ![](https://i-blog.csdnimg.cn/direct/9580bb520dcf4d31a55e86cf823cc232.png) kubectl apply -f db.yaml ![](https://i-blog.csdnimg.cn/direct/648144da6bef4d2d88f97b29832be74e.png) ##### 9.2configmap使用方式 * 通过环境变量的方式直接传递给pod * 通过pod的 命令行运行方式 * 作为volume的方式挂载到pod内 ###### 9.2.1使用configmap填充环境变量 ![](https://i-blog.csdnimg.cn/direct/c82cba47cc1848d1be12c20df0ed768e.png) kubectl apply -f db.yaml vi pod1.yaml ![](https://i-blog.csdnimg.cn/direct/ce3692cdf41342b4ad70c4a33e22bd06.png) ![](https://i-blog.csdnimg.cn/direct/fc057225d62d467282d9d88d52d1c72c.png) | | | |---|---| kubectl logs pods/testpod 查看一下 充当环境变量 在pod命令行中使用变量: ![](https://i-blog.csdnimg.cn/direct/3f5e38fc12b54033915d5ede9d4e6059.png) ![](https://i-blog.csdnimg.cn/direct/2d7ce76ec3b649d28bebb507253fd37d.png) ![](https://i-blog.csdnimg.cn/direct/819eb02ebaa245bab62d5b058f42b5d8.png) pod参数restartPolicy设置了执行以此就ok ![](https://i-blog.csdnimg.cn/direct/2fe98dbb97e44fd5ad4433cf3ad2cc40.png) 查看日志确实执行了该变量 ###### 9.2.2通过数据卷使用configmap ###### 9.2.3通过configmap 充当pod的配置文件 建立模板配置文件: \[root@k8s-master \~\]# vim nginx.conf server { listen 8080; server_name _; root /usr/share/nginx/html; index index.html; } #利用模板生成cm root@k8s-master \~\]# kubectl create cm nginx-conf --from-file nginx.conf configmap/nginx-conf created \[root@k8s-master \~\]# kubectl describe cm nginx-conf Name: nginx-conf Namespace: default Labels: \ Annotations: \ Data ==== nginx.conf: ---- server { listen 8000; server_name _; root /usr/share/nginx/html; index index.html; } BinaryData ==== Events: \ #建立nginx控制器文件 \[root@k8s-master \~\]# kubectl create deployment nginx --image nginx:latest --replicas 1 --dry-run=client -o yaml \> nginx.yml \[root@k8s-master \~\]# cat nginx.yml ![](https://i-blog.csdnimg.cn/direct/0c771089b72a4cfd964dd491343c708a.png) ![](https://i-blog.csdnimg.cn/direct/9c4023c5ebc24a4f931bad6844dabda8.png) 指定的8080端口去访问成功 kubectl edit cm nginx-conf #更改 cm 里的 nginx pod访问端口为80 直接更改完成后 可以删除pod deployment 会重启一个pod然后80端口生效 ![](https://i-blog.csdnimg.cn/direct/fbe8ca70115b45139d5c550c9ca68484.png) 访问成功 ##### 9.3secrets配置管理 * secret 对象类型用来保存敏感信息,例如密码、OAuth 令牌和 ssh key。 * 敏感信息放在 secret 中比放在 Pod 的定义或者容器镜像中来说更加安全和灵活 * Pod 可以用两种方式使用 secret: * 作为 volume 中的文件被挂载到 pod 中的一个或者多个容器里。 * 当 kubelet 为 pod 拉取镜像时使用。 * Secret的类型: * Service Account:Kubernetes 自动创建包含访问 API 凭据的 secret,并自动修改 pod 以使用此类型的 secret。 * Opaque:使用base64编码存储信息,可以通过base64 --decode解码获得原始数据,因此安全性弱。 * kubernetes.io/dockerconfigjson:用于存储docker registry的认证信息 ###### 9.3.1创建方式: 1.用文件的形式进行创建: echo -n timinglee \> username.txt echo -n lee \> password.txt kubectl create secret generic user --from-file username.txt --from-file password.txt ![](https://i-blog.csdnimg.cn/direct/d01eb15feb7445d2bf1d118abfb05803.png) 9.3.2编写yaml文件 ![](https://i-blog.csdnimg.cn/direct/93d7534d04dd452e95c00d82ad8a4492.png) #必须使用base64进行加密 vi user.yaml ![](https://i-blog.csdnimg.cn/direct/4de389d36ba14356870886a1dc664a93.png) kubectl apply -f user.yaml ###### ![](https://i-blog.csdnimg.cn/direct/08787c6e68534309ad03d06cd7ae85aa.png)9.3.2secret使用方式 1.将secret挂载到volume目录中 ![](https://i-blog.csdnimg.cn/direct/d595edaae55d454eb68ef66d949b5d4f.png) 进入容器内部验证一下是否挂载上去 ![](https://i-blog.csdnimg.cn/direct/cd8a7f6021254bdeb62be895c0deb2c7.png) 成功 ###### 9.3.3向指定路径映射secret密钥 ![](https://i-blog.csdnimg.cn/direct/a123da0942bf46ac9fc59f9dd3226cff.png) 进入容器内部查看![](https://i-blog.csdnimg.cn/direct/182ae8a509b34cf7a6b110c2183fdf42.png) ###### 9.3.4将secret设置为环境变量 vi pod3.yaml ![](https://i-blog.csdnimg.cn/direct/903ab4d1216547fbaf9fd6bda5e6030b.png) ![](https://i-blog.csdnimg.cn/direct/6b11102dca774a2ca9d0cab978b92351.png) ###### 9.3.5做docker认证信息 harbor仓库中有些私有镜像必须做认证才能拉取到本地 集群中 首先 建立用于 docker 的secret ![](https://i-blog.csdnimg.cn/direct/0abf6600e99f4f1e83588673f66205ad.png) 编写yaml文件 ![](https://i-blog.csdnimg.cn/direct/baa93deda1774ad6934cce31eb977e53.png) 查看pod成功运行建立 ![](https://i-blog.csdnimg.cn/direct/e298cac6d57a4ad9a9408bea8d9a714d.png) 当不设定imagepullsecrets的时候 下载失败 ![](https://i-blog.csdnimg.cn/direct/b038eb0522554f1897bd45cd2b0a2337.png) ##### 9.4volumes配置 * 容器中文件在磁盘上是临时存放的,这给容器中运行的特殊应用程序带来一些问题 * 当容器崩溃时,kubelet将重新启动容器,容器中的文件将会丢失,因为容器会以干净的状态重建。 * 当在一个 Pod 中同时运行多个容器时,常常需要在这些容器之间共享文件。 * Kubernetes 卷具有明确的生命周期与使用它的 Pod 相同 * 卷比 Pod 中运行的任何容器的存活期都长,在容器重新启动时数据也会得到保留 * 当一个 Pod 不再存在时,卷也将不再存在。 * Kubernetes 可以支持许多类型的卷,Pod 也能同时使用任意数量的卷。 * 卷不能挂载到其他卷,也不能与其他卷有硬链接。 Pod 中的每个容器必须独立地指定每个卷的挂载位置 ###### 9.4.1emptyDir卷 功能: 当Pod指定到某个节点上时,首先创建的是一个emptyDir卷,并且只要 Pod 在该节点上运行,卷就一直存在。卷最初是空的。 尽管 Pod 中的容器挂载 emptyDir 卷的路径可能相同也可能不同,但是这些容器都可以读写 emptyDir 卷中相同的文件。 当 Pod 因为某些原因被从节点上删除时,emptyDir 卷中的数据也会永久删除 emptyDir 的使用场景: * 缓存空间,例如基于磁盘的归并排序。 * 耗时较长的计算任务提供检查点,以便任务能方便地从崩溃前状态恢复执行。 * 在 Web 服务器容器服务数据时,保存内容管理器容器获取的文件 ![](https://i-blog.csdnimg.cn/direct/a591a56b83954270964690390325c57e.png) 一个pod容器运行了俩个镜像 nginx和busyboxplus 共享的是同一个网络 挂载了卷 共享卷里的数据 ![](https://i-blog.csdnimg.cn/direct/c33f137d8dc346ae98308d2c3417e773.png) 测试效果: 在busyboxplus中: kubectl exec -it pods/voll -c vm1 -- /bin/sh ![](https://i-blog.csdnimg.cn/direct/78f9b2eaa1c74c498d80c2872e4bb26a.png) 由于一个pod 里的容器共享网络栈 所以 在cache 中写入index .html文件中的 timignlee curl localhost 出的结果是nginx中默认发布目录中写入的东西 这就是挂载共享卷。 ###### 9.4.2hostpath卷 **hostPath 卷能将主机节点文件系统上的文件或目录挂载到您的 Pod 中,不会因为pod关闭而被删除** * 运行一个需要访问 Docker 引擎内部机制的容器,挂载 /var/lib/docker 路径。 * 在容器中运行 cAdvisor(监控) 时,以 hostPath 方式挂载 /sys。 * 允许 Pod 指定给定的 hostPath 在运行 Pod 之前是否应该存在,是否应该创建以及应该以什么方式存在 hostPath的安全隐患 * 具有相同配置(例如从 podTemplate 创建)的多个 Pod 会由于节点上文件的不同而在不同节点上有不同的行为。 * 当 Kubernetes 按照计划添加资源感知的调度时,这类调度机制将无法考虑由 hostPath 使用的资源。 * 基础主机上创建的文件或目录只能由 root 用户写入。您需要在 特权容器 中以 root 身份运行进程,或者修改主机上的文件权限以便容器能够写入 hostPath 卷。 ![](https://i-blog.csdnimg.cn/direct/a9c229308291450e81887645fa0a835d.png) ![](https://i-blog.csdnimg.cn/direct/9c8a454b26204b66b7c02b8e4be26992.png) node 2 本来没有 /data/是由参数 type 指定的 没有的时候就创建 查看pod状态 pod此刻是运行起来的 并且允许在node2 所以挂载的路径为 node2 上的/data/ ![](https://i-blog.csdnimg.cn/direct/5f3d0ff9b1f54879bb4469df12aa5d8e.png) 在node2写入内容 master访问 curl 10.244.2.71 输出的是hello 是/data/下写入的内容 **删除这个pod之后 /data/下的内容 还是存在 所以实现了数据持久化存储** ###### 9.4.3nfs卷 NFS 卷允许将一个现有的 NFS 服务器上的目录挂载到 Kubernetes 中的 Pod 中。这对于在多个 Pod 之间共享数据或持久化存储数据非常有用 例如,如果有多个容器需要访问相同的数据集,或者需要将容器中的数据持久保存到外部存储,NFS 卷可以提供一种方便的解决方案。 **也是实现存储隔离的方式** 所以节点全部部署 一台是nfs服务器 其他i相当于nfs客户端 dnf install nfs-utils -y systemctl enable --now nfs-server.service vim /etc/exports /nfsdata \*(rw,sync,no_root_squash) \[root@reg \~\]# f's exporting \*:/nfsdata showmount -e 172.25.254.200 #nfs服务器 部署nfs卷 ![](https://i-blog.csdnimg.cn/direct/57592a6b12514cdca78cd0e8d8787468.png) 指明 nfs服务器IP地址 和共享目录 然后创建 ![](https://i-blog.csdnimg.cn/direct/4c9f4fba1cf24daf80fd9ecddbf96f73.png) ![](https://i-blog.csdnimg.cn/direct/75779e0187464cfc9125263adde03bc5.png) 然后在nfs 服务器 echo hello \> index.html curl 10.244.2.61 hello 运行在node2上 实际该数据就存储到了node2上 也实现了存储隔离 ##### 9.5persistentvolume持久卷 静态持久卷pv和静态持久卷声明pvc volumes访问模式 * ReadWriteOnce -- 该volume只能被单个节点以读写的方式映射 * ReadOnlyMany -- 该volume可以被多个节点以只读方式映射 * ReadWriteMany -- 该volume可以被多个节点以读写的方式映射 volumes回收策略 * Retain:保留,需要手动回收 * Recycle:回收,自动删除卷中数据(在当前版本中已经废弃) * Delete:删除,相关联的存储资产,如AWS EBS,GCE PD,Azure Disk,or OpenStack Cinder卷都会被删除 pv * pv是集群内由管理员提供的网络存储的一部分。 * PV也是集群中的一种资源。是一种volume插件, * 但是它的生命周期却是和使用它的Pod相互独立的。 * PV这个API对象,捕获了诸如NFS、ISCSI、或其他云存储系统的实现细节 * pv有两种提供方式:静态和动态 * 静态PV:集群管理员创建多个PV,它们携带着真实存储的详细信息,它们存在于Kubernetes API中,并可用于存储使用 * 动态PV:当管理员创建的静态PV都不匹配用户的PVC时,集群可能会尝试专门地供给volume给PVC。这种供给基于StorageClass pvc * 是用户的一种存储请求 * 它和Pod类似,Pod消耗Node资源,而PVC消耗PV资源 * Pod能够请求特定的资源(如CPU和内存)。PVC能够请求指定的大小和访问的模式持久卷配置 * PVC与PV的绑定是一对一的映射。没找到匹配的PV,那么PVC会无限期得处于unbound未绑定状态 pv相当于仓库 pvc相当于用户的请求 我想要用您pv多少空间 而pod 就是在配置中引用pvc 就能实际使用这个存储空间 vim pv.yaml 先创建pv空间 ![](https://i-blog.csdnimg.cn/direct/47a1288eb7f44e1d83dd0efe988bf86f.png) ![](https://i-blog.csdnimg.cn/direct/798ed7184bf2447392444e45682c637c.png) path 路径 就相当于 存储路径在172.25.254.200:/nfsdata/pv下 storage为pv卷的内存大小 volumeMode为文件系统类型 pvc: pvc1.yaml ![](https://i-blog.csdnimg.cn/direct/b7c76fdd66304fa68b735776e0e3a50a.png) pv和pvc需要吻合 才能使用 pod实例: 创建一个pod 用的是pvc1 的空间 挂载的路径 ![](https://i-blog.csdnimg.cn/direct/1c43e0ddeeb34109b564bb1f83213546.png) ![](https://i-blog.csdnimg.cn/direct/3060ec76fe30414e8d7bb2de9ceb7cce.png) 在 172.25.254.200 pv1/index.html 路径下写入内容 ![](https://i-blog.csdnimg.cn/direct/18710373e15e4110aab69713d8b25c68.png) ![](https://i-blog.csdnimg.cn/direct/cba37d7188c54ca6a5a561aa22922fe1.png) 访问到写入内容 删除pod 后 内容还在 实现了存储持久化 ##### 9.6存储类 storageclass 动态创建 动态收缩 #### 9.7stateful控制器 * tatefulset是为了管理有状态服务的问提设计的 * StatefulSet将应用状态抽象成了两种情况: * 拓扑状态:应用实例必须按照某种顺序启动。新创建的Pod必须和原来Pod的网络标识一样 * 存储状态:应用的多个实例分别绑定了不同存储数据。 * StatefulSet给所有的Pod进行了编号,编号规则是:$(statefulset名称)-$(序号),从0开始。 * Pod被删除后重建,重建Pod的网络标识也不会改变,Pod的拓扑状态按照Pod的"名字+编号"的方式固定下来,并且为每个Pod提供了一个固定且唯一的访问入口,Pod对应的DNS记录。 statefulset 组成部分: * Headless Service:用来定义pod网络标识,生成可解析的DNS记录 * volumeClaimTemplates:创建pvc,指定pvc名称大小,自动创建pvc且pvc由存储类供应。 * StatefulSet:管理pod的 #建立无头服务 (cluster不自动分配ip 直接通过本地 dns解析到pod \[root@k8s-master statefulset\]# vim headless.yml apiVersion: v1 kind: Service metadata: name: nginx-svc labels: app: nginx spec: ports: - port: 80 name: web clusterIP: None selector: app: nginx \[root@k8s-master statefulset\]# kubectl apply -f headless.yml #建立statefulset \[root@k8s-master statefulset\]# vim statefulset.yml apiVersion: apps/v1 kind: StatefulSet metadata: name: web spec: serviceName: "nginx-svc" replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx volumeMounts: - name: www ku mountPath: /usr/share/nginx/html volumeClaimTemplates: - metadata: name: www spec: storageClassName: nfs-client accessModes: - ReadWriteOnce resources: requests: storage: 1Gi \[root@k8s-master statefulset\]# kubectl apply -f statefulset.yml statefulset.apps/web configured root@k8s-master statefulset\]# kubectl get pods NAME READY STATUS RESTARTS AGE web-0 1/1 Running 0 3m26s web-1 1/1 Running 0 3m22s web-2 1/1 Running 0 3m18s \[root@reg nfsdata\]# ls /nfsdata/ default-test-claim-pvc-34b3d968-6c2b-42f9-bbc3-d7a7a02dcbac default-www-web-0-pvc-0390b736-477b-4263-9373-a53d20cc8f9f default-www-web-1-pvc-a5ff1a7b-fea5-4e77-afd4-cdccedbc278c default-www-web-2-pvc-83eff88b-4ae1-4a8a-b042-8899677ae854 #为每个pod建立index.html文件 \[root@reg nfsdata\]# echo web-0 \> default-www-web-0-pvc-0390b736-477b-4263-9373-a53d20cc8f9f/index.html \[root@reg nfsdata\]# echo web-1 \> default-www-web-1-pvc-a5ff1a7b-fea5-4e77-afd4-cdccedbc278c/index.html \[root@reg nfsdata\]# echo web-2 \> default-www-web-2-pvc-83eff88b-4ae1-4a8a-b042-8899677ae854/index.html #建立测试pod访问web-0\~2 \[root@k8s-master statefulset\]# kubectl run -it testpod --image busyboxplus / # curl web-0.nginx-svc web-0 / # curl web-1.nginx-svc web-1 / # curl web-2.nginx-svc web-2 #删掉重新建立statefulset \[root@k8s-master statefulset\]# kubectl delete -f statefulset.yml statefulset.apps "web" deleted \[root@k8s-master statefulset\]# kubectl apply -f statefulset.yml statefulset.apps/web created #访问依然不变 \[root@k8s-master statefulset\]# kubectl attach testpod -c testpod -i -t If you don't see a command prompt, try pressing enter. / # cu curl cut / # curl web-0.nginx-svc web-0 / # curl web-1.nginx-svc web-1 / # curl web-2.nginx-svc web-2 #### 10.k8s通信 ##### 10.1通信整体架构 ###### 1.flannel * k8s通过CNI接口接入其他插件来实现网络通讯。目前比较流行的插件有flannel,calico等 * CNI插件存放位置:# cat /etc/cni/net.d/10-flannel.conflist * 插件使用的解决方案如下 * 虚拟网桥,虚拟网卡,多个容器共用一个虚拟网卡进行通信。 * 多路复用:MacVLAN,多个容器共用一个物理网卡进行通信。 * 硬件交换:SR-LOV,一个物理网卡可以虚拟出多个接口,这个性能最好。 * 容器间通信: * 同一个pod内的多个容器间的通信,通过lo即可实现pod之间的通信 * 同一节点的pod之间通过cni网桥转发数据包。 * 不同节点的pod之间的通信需要网络插件支持 * pod和service通信: 通过iptables或ipvs实现通信,ipvs取代不了iptables,因为ipvs只能做负载均衡,而做不了nat转换 * pod和外网通信:iptables的MASQUERADE * Service与集群外部客户端的通信;(ingress、nodeport、loadbalancer) **同一节点容器内部通信 通过本地的网络插件产生的回环地址 进行通信** **不同节点容器之间的访问:容器container找到 cni(网络接口)然后 通过CNI找到接入的网络插件 flannel flannel通过 VXLAN插件通过对端mac地址然后找到另一个节点上的flannel插件(实际是通过本地网卡eth0 通过arp广播协议 找到 另一个节点eth0到达的)eth0 找到flannel flannel插件通过CNI找到 container从而实现通信 。** ![](https://i-blog.csdnimg.cn/direct/de3f80d9b9044e9cb920975cdfc3795f.png) ###### 2.calino 纯三层转发 中间没有任何NAT和overlay,转发效率最好 calino适配性高 依赖少 ![](https://i-blog.csdnimg.cn/direct/f37d6fcd5c134538b3b47daf82e07975.png) * Felix:监听ECTD中心的存储获取事件,用户创建pod后,Felix负责将其网卡、IP、MAC都设置好,然后在内核的路由表里面写一条,注明这个IP应该到这张网卡。同样如果用户制定了隔离策略,Felix同样会将该策略创建到ACL中,以实现隔离。 * BIRD:一个标准的路由程序,它会从内核里面获取哪一些IP的路由发生了变化,然后通过标准BGP的路由协议扩散到整个其他的宿主机上,让外界都知道这个IP在这里,路由的时候到这里 直接通过 eth0进行访问 本地calino插件中的 BIRD通过arp广播找到其他节点eth0 从而实现通信 calico网络插件部署: 如果提前部署了flannel插件的话需要删除 r m -rf /etc/cni/net.d/\* 下载calino插件到本地 并且上传到本地镜像仓库 ![](https://i-blog.csdnimg.cn/direct/216c7e16e3084035970bbb9b201e66fe.png) 下载calino.yaml到本地 并且做修改: ![](https://i-blog.csdnimg.cn/direct/64551eeadb804f0b8ab16c836ca12e07.png) kubectl apply -f calico.yaml ![](https://i-blog.csdnimg.cn/direct/f6117c1f51064ef8920b98d18fa6008c.png) 查看运行状态为 running ##### 10.2k8s的调度 * 调度是指将未调度的Pod自动分配到集群中的节点的过程 * 调度器通过 kubernetes 的 watch 机制来发现集群中新创建且尚未被调度到 Node 上的 Pod * 调度器会将发现的每一个未调度的 Pod 调度到一个合适的 Node 上来运行 ###### 调度原理: * 创建Pod * 用户通过Kubernetes API创建Pod对象,并在其中指定Pod的资源需求、容器镜像等信息。 * 调度器监视Pod * Kubernetes调度器监视集群中的未调度Pod对象,并为其选择最佳的节点。 * 选择节点 * 调度器通过算法选择最佳的节点,并将Pod绑定到该节点上。调度器选择节点的依据包括节点的资源使用情况、Pod的资源需求、亲和性和反亲和性等。 * 绑定Pod到节点 * 调度器将Pod和节点之间的绑定信息保存在etcd数据库中,以便节点可以获取Pod的调度信息。 * 节点启动Pod * 节点定期检查etcd数据库中的Pod调度信息,并启动相应的Pod。如果节点故障或资源不足,调度器会重新调度Pod,并将其绑定到其他节点上运行。 ###### 调度器种类: * 默认调度器(Default Scheduler): * 是Kubernetes中的默认调度器,负责对新创建的Pod进行调度,并将Pod调度到合适的节点上。 * 自定义调度器(Custom Scheduler): * 是一种自定义的调度器实现,可以根据实际需求来定义调度策略和规则,以实现更灵活和多样化的调度功能。 * 扩展调度器(Extended Scheduler): * 是一种支持调度器扩展器的调度器实现,可以通过调度器扩展器来添加自定义的调度规则和策略,以实现更灵活和多样化的调度功能。 * kube-scheduler是kubernetes中的默认调度器,在kubernetes运行后会自动在控制节点运行 ##### 常用的调度方法: ###### 1.nodename: * nodeName 是节点选择约束的最简单方法,但一般不推荐 * 如果 nodeName 在 PodSpec 中指定了,则它优先于其他的节点选择方法 * 使用 nodeName 来选择节点的一些限制 * 如果指定的节点不存在。 * 如果指定的节点没有资源来容纳 pod,则pod 调度失败。 * 云环境中的节点名称并非总是可预测或稳定的 #建立pod文件 \[\[root@k8s-master scheduler\]# kubectl run testpod --image myapp:v1 --dry-run=client -o yaml \> pod1.yml #设置调度 \[root@k8s-master scheduler\]# vim pod1.yml apiVersion: v1 kind: Pod metadata: labels: run: testpod name: testpod **spec: nodeName: k8s-node2** containers: - image: myapp:v1 name: testpod #建立pod \[root@k8s-master scheduler\]# kubectl apply -f pod1.yml pod/testpod created \[root@k8s-master scheduler\]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES testpod 1/1 Running 0 18s 10.244.169.130 **k8s-node2** \ \ nodeName: k8s3 #**找不到节点pod会出现pending,优先级最高,其他调度方式无效5** ###### 2.Nodeselectot(通过标签控制节点) nodeSelector 是节点选择约束的最简单推荐形式 给选择的节点添加标签: kubectl label nodes node1 lab=lee #设置node1的label为lee 可以给多个节点设定相同标签 查看 node1label已经设置为lee ![](https://i-blog.csdnimg.cn/direct/27def07022fd47b291cde5c16156f4e8.png) ![](https://i-blog.csdnimg.cn/direct/0b7fffa3b6954e18ac77dc66f01c3426.png)yaml中 指定nodeselector调度标签为lee 所以该pod调度到node1上 ![](https://i-blog.csdnimg.cn/direct/7f00dd1d14494458a90b51abb9931eb9.png) ###### 亲和性(affinity): * nodeSelector 提供了一种非常简单的方法来将 pod 约束到具有特定标签的节点上。亲和/反亲和功能极大地扩展了你可以表达约束的类型。 * 使用节点上的 pod 的标签来约束,**而不是使用节点本身的标签**,来允许哪些 pod 可以或者不可以被放置在一起。 ###### nodeAffinity节点亲和: * 那个节点服务指定条件就在那个节点运行 * requiredDuringSchedulingIgnoredDuringExecution 必须满足,但不会影响已经调度(在调度 Pod 时必须满足此规则,但在 Pod 运行期间如果节点标签发生变化,不会影响 Pod 的运行) * preferredDuringSchedulingIgnoredDuringExecution 倾向满足,在无法满足情况下也会调度pod * IgnoreDuringExecution 表示如果在Pod运行期间Node的标签发生变化,导致亲和性策略不能满足,则继续运行当前的Pod。 * nodeaffinity还支持多种规则匹配条件的配置如 | 匹配规则 | 功能 | |--------------|--------------------------| | ln | label 的值在列表内 | | Notln | label 的值不在列表内 | | Gt | label 的值大于设置的值,不支持Pod亲和性 | | Lt | label 的值小于设置的值,不支持pod亲和性 | | Exists | 设置的label 存在 | | DoesNotExist | 设置的 label 不存在 | kubectl label nodes node1 gpu=hxd #自定义键值对标签 随便设置 pod如下 : affinity下的nodeAffinity亲和性配置 "requiredDuringSchedulingIgnoredDuringExecution":这是一种节点亲和性规则,意思是在调度 Pod 时必须满足此规则,但在 Pod 运行期间如果节点标签发生变化,不会影响 Pod 的运行。 nodeSelectorTerms" 数组:包含节点选择器条件 "matchExpressions" 数组:具体的匹配表达式。 key为匹配的标签键为gpu "operator: In \| NotIn":操作符为 In(表示节点标签值在给定列表中)或 NotIn(表示节点标签值不在给定列表中),注释说明这两个操作符结果相反 values" 数组: * "- hxd":如果操作符是 In,意味着节点标签 disk 的值为 ssd 的节点才符合调度要求;如果是 NotIn,则表示节点标签 disk 的值不为 hxd 的节点才符合调度要求。 ![](https://i-blog.csdnimg.cn/direct/096d8ea73e944fab962efd897d4c7a72.png) ![](https://i-blog.csdnimg.cn/direct/24845bd2b089458e90836e0ed68d885f.png) 如图调度到node1上面 ![](https://i-blog.csdnimg.cn/direct/88084f5b23b6493ca7483ac45c3f95d3.png) ###### Podaffinity(pod)的亲和 * 那个节点有符合条件的POD就在那个节点运行 * podAffinity 主要解决POD可以和哪些POD部署在同一个节点中的问题 * podAntiAffinity主要解决POD不能和哪些POD部署在同一个节点中的问题。它们处理的是Kubernetes集群内部POD和POD之间的关系。 * Pod 间亲和与反亲和在与更高级别的集合(例如 ReplicaSets,StatefulSets,Deployments 等)一起使用时,Pod 间亲和与反亲和需要大量的处理,这可能会显著减慢大规模集群中的调度。 ![](https://i-blog.csdnimg.cn/direct/30d8c11d0b4c445f99399226078c5795.png) 亲和性参数为podAffinity ![](https://i-blog.csdnimg.cn/direct/d279984c96974668a5e0c0be7beede5b.png) 设置了节点亲和性 都在一个节点上运行 3个pod 匹配的键为 topologyKey 为拓扑标签 节点上有这个标签才能被调度过去 ###### pod的反亲和: podAniAffinity参数 ![](https://i-blog.csdnimg.cn/direct/d68126acacc44c1797a40c9fa7656ab5.png) 一个节点调度到一个pod 俩个节点各有一个 多余的pod 显示pending状态。 ###### Taints污点: | effect值 | 解释 | |------------------|----------------------------------------| | NoSchedule | POD 不会被调度到标记为 taints 节点 | | PreferNoSchedule | NoSchedule 的软策略版本,尽量不调度到此节点 | | NoExecute | 如该节点内正在运行的 POD 没有对应 Tolerate 设置,会直接被逐出 | 给某个节点打上污点以后,该节点无法调度到pods kubectl describe nodes node1 \| grep Taints #查看某个节点是否打上污点 kubectl taint nodes node1 key=string:NoSchedule 给node1节点打上 不调度的污点' kubectl taint node node1 key- #删除该节点污点 kubectl get nodes k8s-node1 -o json \| jq '.spec.taints' #查询多个污点 创建一个pod ![](https://i-blog.csdnimg.cn/direct/0195f07dc2dd4ac8a9ee85ace88612ae.png) ![](https://i-blog.csdnimg.cn/direct/bf07143eb0c34d40bc1d561adb57172f.png) 全部运行在node2上面 kubectl scale deployment web --replicas=6 增加pod数量 查看 也是全部调度到node2上 这就是node1 taints:NoSchedule的作用 ![](https://i-blog.csdnimg.cn/direct/65cb63d71bf74c03a706f4300dab1502.png) ###### 污点容忍: 运行pod 定义污点容忍为 ![](https://i-blog.csdnimg.cn/direct/2d00bf86fa8f45e6934b5ce56211ea24.png) ![](https://i-blog.csdnimg.cn/direct/d97add682b6a4cf2b1fa6ea2fa559bff.png) 以上为容忍所有污点 ![](https://i-blog.csdnimg.cn/direct/d14085b0eafe44a2b8806ff1f774b719.png) 容忍 NoSchedule的污点 给 node2 添加一个污点 kubectl taint nodes node2 name=lee:PreferNoSchedule ![](https://i-blog.csdnimg.cn/direct/3ff1524a338e4fbc82adc9bc2066c08d.png) ![](https://i-blog.csdnimg.cn/direct/8e925778bf914f17a7f34e9cb02a77e9.png) 添加这个tolerations 表示 对该打上该污点的节点进行容忍 查看pod运行位置 没有node2 ![](https://i-blog.csdnimg.cn/direct/63b3ba09f98748ccad769f24b8194734.png) ##### 11.k8s中api访问控制 Authentication(认证) * 认证方式现共有8种,可以启用一种或多种认证方式,只要有一种认证方式通过,就不再进行其它方式的认证。通常启用X509 Client Certs和Service Accout Tokens两种认证方式。 * Kubernetes集群有两类用户:由Kubernetes管理的Service Accounts (服务账户)和(Users Accounts) 普通账户。k8s中账号的概念不是我们理解的账号,它并不真的存在,它只是形式上存在。 userAccount service accounts ##### 12.helm包管理 helm 类似于 yum源 作为k8s中软件包的管理工具 ###### 12.0.1部署helm: \[root@k8s-master helm\]# tar zxf helm-v3.15.4-linux-amd64.tar.gz \[root@k8s-master helm\]# ls helm-v3.15.4-linux-amd64.tar.gz linux-amd64 \[root@k8s-master helm\]# cd linux-amd64/ \[root@k8s-master linux-amd64\]# ls helm LICENSE README.md \[root@k8s-master linux-amd64\]# cp -p helm /usr/local/bin/ #"-p" 是一个选项参数,其作用是在复制文件时,保留源文件的属性,包括文件的所有者、所属组、权限以及修改时间等。 补齐helm命令 \[root@k8s-master linux-amd64\]# echo "source \<(helm completion bash)" \>\> \~/.bashrc \[root@k8s-master linux-amd64\]# source \~/.bashrc \[root@k8s-master linux-amd64\]# helm version version.BuildInfo{Version:"v3.15.4", GitCommit:"fa9efb07d9d8debbb4306d72af76a383895aa8c4", GitTreeState:"clean", GoVersion:"go1.22.6"} | **命令** | **描述** | |------------|-------------------------------------------------------------| | create | 创建一个 chart 并指定名字 | | dependency | 管理 chart 依赖 | | get | 下载一个 release。可用子命令:all、hooks、manifest、notes、values | | history | 获取 release 历史 | | install | 安装一个 chart | | list | 列出 release | | package | 将 chart 目录打包到 chart 存档文件中 | | pull | 从远程仓库中下载 chart 并解压到本地 # helm pull stable/mysql -- untar | | repo | 添加,列出,移除,更新和索引 chart 仓库。可用子命令:add、index、 list、remove、update | | rollback | 从之前版本回滚 | | search | 根据关键字搜索 chart。可用子命令:hub、repo | | show | 查看 chart 详细信息。可用子命令:all、chart、readme、values | | status | 显示已命名版本的状态 | | template | 本地呈现模板 | | uninstall | 卸载一个 release | | upgrade | 更新一个 release | | version | 查看 helm 客户端版本 | 管理第三方repo源: * 阿里云仓库:[https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts](https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts "https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts") * bitnami仓库: [https://charts.bitnami.com/bitnami](https://charts.bitnami.com/bitnami "https://charts.bitnami.com/bitnami") * 微软仓库:[Index of /kubernetes/charts/](http://mirror.azure.cn/kubernetes/charts/ "Index of /kubernetes/charts/") * 官方仓库: [https://hub.kubeapps.com/charts/incubator](https://hub.kubeapps.com/charts/incubator "https://hub.kubeapps.com/charts/incubator") #添加阿里云仓库 \[root@k8s-master helm\]# helm repo add aliyun https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts "aliyun" has been added to your repositories #添加bitnami仓库 \[root@k8s-master helm\]# helm repo add bitnami https://charts.bitnami.com/bitnami "bitnami" has been added to your repositories #查看仓库信息 \[root@k8s-master helm\]# helm repo list NAME URL aliyun https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts bitnami https://charts.bitnami.com/bitnami #查看仓库存储helm清单 \[root@k8s-master helm\]# helm search repo aliyun NAME CHART VERSION APP VERSION DESCRIPTION #应用名称 封装版本 软件版本 软件描述 aliyun/acs-engine-autoscaler 2.1.3 2.1.1 Scales worker nodes within agent pools aliyun/aerospike 0.1.7 v3.14.1.2 A Helm chart for Aerospike in Kubernetes #删除第三方存储库 \[root@k8s-master helm\]# helm repo list NAME URL aliyun https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts bitnami https://charts.bitnami.com/bitnami \[root@k8s-master helm\]# helm repo remove aliyun "aliyun" has been removed from your repositories \[root@k8s-master helm\]# helm repo list NAME URL bitnami https://charts.bitnami.com/bitnami ###### 12.0.2 构建简单的charts项目 helm create hxd #创建一个名为hxd的charts包 tree hxd ![](https://i-blog.csdnimg.cn/direct/f70dc754c29a4b2b932bedf8dffeba1e.png) vi Charts.yaml ![](https://i-blog.csdnimg.cn/direct/32f771e63aa34e7babbdad504c31e1e0.png) vi values.yaml 镜像拉取位置 ![](https://i-blog.csdnimg.cn/direct/28206dc2b3ab43d7ae2aba86314a2250.png) 服务的域名: ![](https://i-blog.csdnimg.cn/direct/df7ac06fb7614f10812271b595717223.png) 查看创建的ingress的类 ![](https://i-blog.csdnimg.cn/direct/acd67a1088bd448eae66ff2ecf29f3f7.png) 需要调用才能通过ingress 实现服务的对外暴露 ![](https://i-blog.csdnimg.cn/direct/c96d217c9192463e910a1cb436be0cd0.png) 访问域名测试: ![](https://i-blog.csdnimg.cn/direct/79b0e596be15402da29f604512aaba24.png) helm lint 跟路径 #检查有没有语法问题 ![](https://i-blog.csdnimg.cn/direct/ef95820f0cae41ccb0b665d2129e85e5.png) 打包# helm package hxd/![](https://i-blog.csdnimg.cn/direct/01b8e6862a3c4da18fd3d3bc0aa4df89.png) ![](https://i-blog.csdnimg.cn/direct/fc936d3d4a234839b1a2efff0adb3884.png) ###### 12.0.3 helm仓库 用于存放自己构建的charts项目 然后helm 本身没有上传功能 需要helm push插件支持。 在线安装一下 dnf install git -y helm plugin install https://github.com/chartmuseum/helm-push 添加仓库: 现在harbor本地添加一个项目 项目名为 hxd ![](https://i-blog.csdnimg.cn/direct/cf53dbf0f90d4a37b91fc9fe49ca8dd9.png) 给helm 添加证书 cp /etc/docker/certs.d/certs/timinglee.org.crt /etc/pki/ca-trust/source/anchors/ update-ca-trust 添加仓库: helm repo add hxd **https://reg.timinglee.org/chartrepo/**hxd ![](https://i-blog.csdnimg.cn/direct/0ca7cca6e0754af0b6eea8d8fe9c8c19.png) 上传项目: #命令执行格式 helm cm-push \<项目名称\> \<仓库名称\> -u admin -p lee ![](https://i-blog.csdnimg.cn/direct/4781e8e484874ce2a10b7f8ff67242db.png) ![](https://i-blog.csdnimg.cn/direct/54a4ad7cbe7d45489bff857f4c6d278b.png) 上传成功 ![](https://i-blog.csdnimg.cn/direct/9dc9c156e8f644b0b8c3a1e7a78177e8.png) 查看是否上传成功命令 需要先刷新仓库 #下载仓库里的项目 ![](https://i-blog.csdnimg.cn/direct/54d208e1a5d14c8ab48f6dca88de5a82.png) helm search repo hxd/ #查看项目 helm install 仓库名 项目名 #安装项目 可以加--version 指定版本 ###### 12.0.4 helm的版本迭代 helm search repo hxd -l #查看名为hxd的仓库中存在的charts项目 版本迭代 版本首先都需要 存在于harbor项目中 ![](https://i-blog.csdnimg.cn/direct/245bc325c9d340c997c9bc82902023d4.png) helm list -a #查看本地已经安装的软件包 #myapp版本为v1 ![](https://i-blog.csdnimg.cn/direct/ff28caf8c1d54da6aa7ee7788c5890a3.png) helm upgrade myapp hxd/myapp #更新版本 ![](https://i-blog.csdnimg.cn/direct/4d4e997d74964617a4cc314c3e0729c5.png) myapp已经成功更新为v2 helm rollback myapp #版本回滚 helm history myapp #查看历史版本 ![](https://i-blog.csdnimg.cn/direct/11b54e8f23a2471ca6de6ef4c3f05b9f.png) #### 13.普罗米修斯 Prometheus是一个开源的服务监控系统和时序数据库 其提供了通用的数据模型和快捷数据采集、存储和查询接口 它的核心组件Prometheus服务器定期从静态配置的监控目标或者基于服务发现自动配置的目标中进行拉取数据 新拉取到啊的 数据大于配置的内存缓存区时,数据就会持久化到存储设备当中 ###### 13.1使用helm部署普罗米修斯:

相关推荐
youmeyoume21653 小时前
k8s +cilium+metallb 集群流量走向
云原生·容器·kubernetes
Monika Zhang4 小时前
云原生开发全面解析:从核心理念到实践挑战与解决方案
云原生
北极糊的狐4 小时前
启动模块服务时报错:docker: Error response from daemon: Conflict.
运维·docker·容器
Monika Zhang6 小时前
2025年最新云原生开发方案全景解析
云原生
David爱编程6 小时前
使用DaemonSet部署日志/监控类组件的正确姿势
云原生·容器·kubernetes
__Smile°8 小时前
kubeadm-k8s 中的 etcd 备份与恢复
数据库·docker·云原生·容器·kubernetes·etcd
小醉你真好9 小时前
12、Docker Compose 安装 Redis
redis·docker·容器
慌ZHANG9 小时前
云原生安全挑战与治理策略:从架构思维到落地实践
大数据·云原生·架构
lovebugs10 小时前
Kubernetes中高效获取Java应用JVM参数的终极指南
后端·docker·kubernetes