中国有名的模版网站,常见的网络推广工具,网站建设工作策划方案,wordpress评论框required1. K8S 概览
1.1 K8S 是什么
K8S官网文档#xff1a;https://kubernetes.io/zh/docs/home/ 1.2 K8S核心特性
服务发现与负载均衡#xff1a;无需修改你的应用程序即可使用陌生的服务发现机制。存储编排#xff1a;自动挂载所选存储系统#xff0c;包括本地存储。Secret和…
1. K8S 概览
1.1 K8S 是什么
K8S官网文档https://kubernetes.io/zh/docs/home/ 1.2 K8S核心特性
服务发现与负载均衡无需修改你的应用程序即可使用陌生的服务发现机制。存储编排自动挂载所选存储系统包括本地存储。Secret和配置管理部署更新Secrets和应用程序的配置时不必重新构建容器镜像且不必将软件堆栈配置中的秘密信息暴露出来。批量执行除了服务之外Kubernetes还可以管理你的批处理和CI工作负载在期望时替换掉失效的容器。水平扩缩使用一个简单的命令、一个UI或基于CPU使用情况自动对应用程序进行扩缩。自动化上线和回滚Kubernetes会分步骤地将针对应用或其配置的更改上线同时监视应用程序运行状况以确保你不会同时终止所有实例。自动装箱根据资源需求和其他约束自动放置容器同时避免影响可用性。自我修复重新启动失败的容器在节点死亡时替换并重新调度容器杀死不响应用户定义的健康检查的容器。
1.3 K8S 核心架构
我们已经知道了 K8S 的核心功能自动化运维管理多个容器化程序。那么 K8S 怎么做到的呢这里我们从宏观架构上来学习 K8S 的设计思想。首先看下图 K8S 是属于Master-Worker架构即有 Master 节点负责核心的调度、管理和运维Worker 节点则 执行用户的程序。但是在 K8S 中主节点一般被称为Master Node 而从节点则被称为Worker Node 或者 Node。
注意Master Node 和 Worker Node 是分别安装了 K8S 的 Master 和 Woker 组件的实体服务器 每个 Node 都对应了一台实体服务器虽然 Master Node 可以和其中一个 Worker Node 安装在同 一台服务器但是建议 Master Node 单独部署所有 Master Node 和 Worker Node 组成了 K8S 集群同一个集群可能存在多个 Master Node 和 Worker Node。
首先来看Master Node都有哪些组件
kube-apiserver。K8S 的请求入口服务。API Server 负责接收 K8S 所有请求来自 UI 界面或者CLI命令行工具然后API Server 根据用户的具体请求去通知其他组件干活。Scheduler。K8S 所有 Worker Node 的调度器。当用户要部署服务时Scheduler 会选择最合适的 Worker Node服务器来部署。Controller Manager。K8S 所有 Worker Node 的监控器。Controller Manager 有很多具体的 ControllerNode Controller、Service Controller、Volume Controller等。Controller 负责监控和调整在 Worker Node上部署的服务的状态比如用户要求 A 服务部署 2个副本那么当其中一个服务挂了的时候Controller 会马上调整让 Scheduler 再选择一个 Worker Node 重新部署服务。etcd。K8S 的存储服务。etcd 存储了 K8S 的关键配置和用户配置K8S 中仅 API Server 才具备读写权限其他组件必须通过 API Server 的接口才能读写数据。
接着来看Worker Node的组件
Kubelet。Worker Node 的监视器以及与 Master Node 的通讯器。Kubelet 是 Master Node 安插在 Worker Node 上的“眼线”它会定期向 Master Node 汇报自己 Node上运行的服务的状态并接受来自Master Node 的指示采取调整措施。负责控制所有容器的启动停止保证节点工作正常。Kube-Proxy。K8S 的网络代理。Kube-Proxy 负责 Node 在 K8S 的网络通讯、以及对外部网络流量的负载均衡。Container Runtime。Worker Node 的运行环境。即安装了容器化所需的软件环境确保容器化程序能够跑起来比如 Docker Engine运行环境
2、K8S安装教程
视频地址图灵K8S
2.1. 安装要求
3台以上机器操作系统 CentOS7.7以上64位系统硬件配置2GB或更多RAM2个CPU或更多CPU硬盘30GB或更多集群中所有机器之间网络互通可以访问外网需要拉取镜像禁止swap分区
2.2. centos7兼容版本(7.7~7.9) 2.3. 三台主机
搭建k8s集群三台主机每台至少2G以上
主机 说明
主机说明192.168.23.201k8s-master192.168.23.202k8s-node1192.168.23.203k8s-node2
备注本次装机选用k8s 1.19.16版本dokcer1.18.09版本
主机安装参考链接这里只参考第六集
黑马k8s第六集
2.4. 安装docker(三台主机都需要安装)
#卸载旧版本
sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-enginesudo yum update -ysudo yum install -y yum-utils device-mapper-persistent-data lvm2#配置docker的yum地址
sudo yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo#安装指定docker版本
sudo yum -y install docker-ce-18.09.9 docker-ce-cli-18.09.9 containerd.io#启动dokcer并开机自启
sudo systemctl start docker
sudo systemctl enable docker#Docker配置修改
vim /etc/docker/daemon.json{graph: /data/docker,registry-mirrors: [https://xv8xjvpp.mirror.aliyuncs.com,https://docker.m.daocloud.io/,https://dockerproxy.com/,https://mirror.baidubce.com/,https://docker.nju.edu.cn/,https://ccr.ccs.tencentyun.com/ ],exec-opts: [native.cgroupdriversystemd],log-driver: json-file,log-opts: {max-size: 100m},storage-driver: overlay2
}
#加载配置文件并重启docker
sudo systemctl daemon-reload
sudo systemctl restart docker常见错误 如果yum update失败需要进行更换镜像下面以清华镜像为例, 三台机器都要操作
打开配置yum所在文件CentOS-Base.repo
vi /etc/yum.repos.d/CentOS-Base.repo将CentOS-Base.repo里的内容全部替换为以下内容
# CentOS-Base.repo
[base]
nameCentOS-$releasever - Base
baseurlhttp://mirrors.aliyun.com/centos/$releasever/os/$basearch/ http://mirrors.tuna.tsinghua.edu.cn/centos/$releasever/os/$basearch/
gpgcheck1
gpgkeyfile:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 #released updates
[updates]
nameCentOS-$releasever - Updates
baseurlhttp://mirrors.aliyun.com/centos/$releasever/updates/$basearch/ http://mirrors.tuna.tsinghua.edu.cn/centos/$releasever/updates/$basearch/
gpgcheck1
gpgkeyfile:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 #additional packages that may be useful
[extras]
nameCentOS-$releasever - Extras
baseurlhttp://mirrors.aliyun.com/centos/$releasever/extras/$basearch/ http://mirrors.tuna.tsinghua.edu.cn/centos/$releasever/extras/$basearch/
gpgcheck1
gpgkeyfile:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 #additional packages that extend functionality of existing packages
[centosplus]
nameCentOS-$releasever - Plus
baseurlhttp://mirrors.aliyun.com/centos/$releasever/centosplus/$basearch/ http://mirrors.tuna.tsinghua.edu.cn/centos/$releasever/centosplus/$basearch/
gpgcheck1
enabled0
gpgkeyfile:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 #contrib - packages by Centos Users
[contrib]
nameCentOS-$releasever - Contrib
baseurlhttp://mirrors.aliyun.com/centos/$releasever/contrib/$basearch/ http://mirrors.tuna.tsinghua.edu.cn/centos/$releasever/contrib/$basearch/
gpgcheck1
enabled0
gpgkeyfile:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 # 使用failovermethod指定优先级这里设置为随机roundrobin也可以改为priority并指定每个URL的优先级
failovermethodroundrobin
清理YUM缓存并更新更新完之后再安装Docker
yum clean all
yum makecache
yum update2.5. 主机环境配置(三台都需要)
#1.关闭防火墙
sudo systemctl stop firewalld
sudo systemctl disable firewalld#2.关闭selinux
#selinux禁用
setenforce 0
sed -i s/enforcing/disabled/ /etc/selinux/config#2.关闭swap分区
swapoff -a
vim /etc/fstab # 注释到swap那一行 永久关闭#3.设置主机名
hostnamectl set-hostname k8s-master
hostnamectl set-hostname k8s-node1
hostnamectl set-hostname k8s-node2#4.添加host,IP需要改成你自己机器的IP
cat /etc/hosts EOF
192.168.23.201 k8s-master
192.168.23.202 k8s-node1
192.168.23.203 k8s-node2
EOF#5.允许iptables 检查桥接流量
cat /etc/sysctl.d/k8s.conf EOF
net.ipv4.ip_forward 1
net.ipv4.tcp_tw_recycle 0
net.bridge.bridge-nf-call-ip6tables 1
net.bridge.bridge-nf-call-iptables 1
EOF
sysctl --system#6.设置时间同步
yum install -y ntpdate
ntpdate time.windows.com
2.6. 安装kubelet,kubeadm,kubectl(三台机器都需要执行)
#1.配置k8s的yum源
cat EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
nameKubernetes
baseurlhttps://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled1
gpgcheck1
repo_gpgcheck1
gpgkeyhttps://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF#2.如果之前安装了k8s,先卸载旧版本
yum -y remove kubelet kubeadm kubectl#3.查看可以安装的版本#可以将 kubelet 替换为 kubeadm 或 kubectl以查看相应组件的可用版本
yum list --showduplicates kubelet | sort -r #4安装指定的kubeletkubeadmkubectl版本
sudo yum install -y kubelet-1.19.16 kubeadm-1.19.16 kubectl-1.19.16# 启动kubelet并卡机自启
sudo systemctl start kubelet
sudo systemctl enable kubelet#检查k8s是否启动
sudo systemctl status kubelet#排查错误
journalctl -xefu kubelet#master主机上执行
# 下载镜像。
# 此镜像 kubernetes 的仓库中由于网络原因无法连接下面提供了一种替换方案。
images(kube-apiserver:v1.19.16kube-controller-manager:v1.19.16kube-scheduler:v1.19.16kube-proxy:v1.19.16pause:3.2etcd:3.4.13-0coredns:1.7.0
)for imageName in ${images[]};dodocker pull registry.cn-hangzhou.aliyuncs.com/google_containers/$imageNamedocker tag registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName k8s.gcr.io/$imageNamedocker rmi registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName
donekubeadm init \--apiserver-advertise-address192.168.23.201 \--image-repositoryregistry.aliyuncs.com/google_containers \--kubernetes-versionv1.19.16 \--pod-network-cidr192.168.0.0/16 \--service-cidr10.96.0.0/12#master主机上执行
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
export KUBECONFIG/etc/kubernetes/admin.conf#手动拉取(三台机器都要)
docker pull docker.io/calico/cni:v3.20.6
docker pull docker.io/calico/kube-controllers:v3.20.6
docker pull docker.io/calico/node:v3.20.6#安装网络插件 Calico(仅master主机需要)
#下载calico.yaml
mkdir /root/k8s
cd /root/k8s
wget https://docs.projectcalico.org/v3.20/manifests/calico.yaml
kubectl apply -f calico.yaml#申请一个新令牌
kubeadm token create --print-join-command#加入node节
#复制新生成的令牌
kubeadm join 192.168.23.201:6443 --token xxxx --discovery-token-ca-cert-hash sha256:xxxxx
三个节点都是Ready表示搭建成功 3. K8S基础命令
3.1 kubectl命令使用
使用kubectl 查看
Cluster Management Commands:certificate 修改 certificate 资源.cluster-info 显示集群信息top Display Resource (CPU/Memory/Storage) usage.cordon 标记 node 为 unschedulableuncordon 标记 node 为 schedulabledrain Drain node in preparation for maintenancetaint 更新一个或者多个 node 上的 taintsTroubleshooting and Debugging Commands:describe 显示一个指定 resource 或者 group 的 resources 详情logs 输出容器在 pod 中的日志attach Attach 到一个运行中的 containerexec 在一个 container 中执行一个命令port-forward Forward one or more local ports to a podproxy 运行一个 proxy 到 Kubernetes API servercp 复制 files 和 directories 到 containers 和从容器中复制 files 和 directories.auth Inspect authorizationAdvanced Commands:diff Diff live version against would-be applied versionapply 通过文件名或标准输入流(stdin)对资源进行配置patch 使用 strategic merge patch 更新一个资源的 field(s)replace 通过 filename 或者 stdin替换一个资源wait Experimental: Wait for a specific condition on one or many resources.convert 在不同的 API versions 转换配置文件kustomize Build a kustomization target from a directory or a remote url.Settings Commands:label 更新在这个资源上的 labelsannotate 更新一个资源的注解completion Output shell completion code for the specified shell (bash or zsh)Other Commands:alpha Commands for features in alphaapi-resources Print the supported API resources on the serverapi-versions Print the supported API versions on the server, in the form of group/versionconfig 修改 kubeconfig 文件plugin Provides utilities for interacting with plugins.version 输出 client 和 server 的版本信息
3.2 Namespace
k8s中命名空间(Namespace) 提供一种机制同一集群中的资源划分为相互隔离的组同一命名空间内的资源名称要唯一命名空间是用来隔离资源的不隔离网路。
kubernetes启动时会创建四个初始命名空间 default kubernetes包含这个命名空间以便你无需创建新的命名空间即可开始使用新集群 kube-node-lease 该命名空间包含用于各个节点关联的Lease(租约)对象。节点租约允许kubelet发送心跳由此控制能够检测到节点故障。 kube-public 所有的客户端(包括未经身份验证的客户端)都可以读取该命名空间。该命名空间主要预留未集群使用以便某些资源需要在整个集群中可见可读。该命名空间的公属性是一种约定而非要求。 kube-system 该命名空间使用kubernetes系统创建的对象。 #查看namespace
kubectl get namespace
#查看kube-system下的pod
kubectl get pods -n kube-system
#查看所有namespace下的pod
kubectl get pods -A创建Namespace 命令行方式
kubectl create namespace XXXXXyaml方式
新建一个名为 my-namespace.yaml 的 YAML 文件并写入下列内容
#XXXXX.yaml
apiVersion: v1
kind: Namespace
metadata:name: my-namespace然后运行
kubectl create -f XXXXX.yaml删除namespace
kubectl delete namespace XXXXX
kubectl delete -f XXXXX.yaml3.3 Pod 创建Pod示例运行一个NGINX容器
命令方式
#创建pod
kubectl run mynginx --imagenginx:1.14#获取pod的信息-owide 表示更详细的显示信息 -n 命名空间 查询对应namespace下的pod
kubectl get pod
kubectl get pod -owide
kubectl get pod -n namespace-name#查看pod的详情
kubctl describe pod pod-name#查看pod的运行日志
kubectl logs pod-name
#删除pod
kubectl delete pod pod-nameyaml方式
#nginx-pod.yaml
apiVersion: v1
kind: Pod
metadata:labels:run: mynginxname: mynginx
spec:containers:- name: nginximage: nginx:1.14.2ports:- containerPort: 80部署成功访问nginx 3.4 Deployment
Deployment负责创建和更新应用程序的实例使Pod拥有多副本自愈扩容等能力。创建Deployment后kubernetes master将应用程序实列调整到集群中的各个节点上。如果托管实列的节点关闭或被删除Deployment控制器会将该实例替换为集群中另一个节点上的实例这提供了一种自我修复机制来解决机器故障维护问腿。 创建一个Tomcat应用程序
使用 kubectl create deployment 命令可以创建一个应用部署deployment与pod #my-tomcat表示pod的名称 --image表示镜像的地址 kubectl create deployment my-tomcat --imagetomcat:9.0.55#查看一下deployment的信息kubectl get deployment#删除deploymentkubectl delete deployment my-tomcat#查看Pod打印的日志kubectl logs my-tomcat-6d6b57c8c8-n5gm4#使用 exec 可以在Pod的容器中执行命令kubectl exec my-tomcat-6d6b57c8c8-n5gm4 -- env #使用 env 命令查看环境变量kubectl exec my-tomcat-6d6b57c8c8-n5gm4 -- ls / # 查看容器的根目录下面内容kubectl exec my-tomcat-6d6b57c8c8-n5gm4 -- sh #进入Pod容器内部并执行bash命令如果想退出
容器可以使用exit命令 思考下面两个命令有什么区别? kubectl create my-tomcat --imagetomcat:9.0.55
kubectl create deployment my-tomcat --imagetomcat:9.0.55自愈 现在我们来删除刚刚添加的pod看看会发生什么 #查看pod信息-w意思是一直等待观察pod信息的变动kubectl get pod -w开另外一个命令窗口执行如下命令同时观察之前命令窗口的变化情况 kubectl delete pod my-tomcat-6d6b57c8c8-n5gm4我们可以看到之前那个tomcat的pod被销毁但是又重新启动了一个新的tomcat pod 这是k8s的服务自愈功能不需要运维人员干预
多副本
命令行的方式 # 创建3个副本kubectl create deployment my-tomcat --imagetomcat:9.0.55 --replicas3yaml方式
apiVersion: apps/v1
kind: Deployment
metadata:name: tomcat-deploymentlabels:app: tomcat-deployment
spec:replicas: 3 # 定义了 3 个副本selector:matchLabels:app: tomcat-deploymenttemplate:metadata:labels:app: tomcat-deploymentspec:containers:- name: tomcatimage: tomcat:9.0.55
扩缩容 # 扩容到5个podkubectl scale --replicas5 deployment my-tomcat# 缩到3个podkubectl scale --replicas3 deployment my-tomcat#修改 replicaskubectl edit deployment my-tomcat滚动升级与回滚
对my-tomcat这个deployment进行滚动升级和回滚将tomcat版本由tomcat:9.0.55升级到 tomcat:10.1.11再回滚到tomcat:9.0.55 滚动升级 kubectl set image deployment my-tomcat tomcattomcat:10.1.11 --record可以执行 kubectl get pod -w 观察pod的变动情况可以看到有的pod在销毁有的pod在创建 查看pod信息 kubectl get pod查看某个pod的详细信息发现pod里的镜像版本已经升级了
kubectl describe pod my-tomcat-85c5c8f685-lnkfm版本回滚 查看历史版本 kubectl rollout history deploy my-tomcat回滚到上一个版本 kubectl rollout undo deployment my-tomcat #--to-revision 参数可以指定回退的版本#回滚(回到指定版本)kubectl rollout undo deployment/my-dep --to-revision2查看pod详情发现版本已经回退了
访问tomcat pod
集群内访问在集群里任一worker节点都可以访问 curl 192.168.36.74:8080集群外部访问
当我们在集群之外访问是发现无法访问那么集群之外的客户端如何才能访问呢这就需要我们的 service服务了下面我们就创建一个service使外部客户端可以访问我们的pod
3.5 Service 创建service示例
命令行形式
kubectl expose deployment my-tomcat --port8080 --typeNodePort#查看service信息port信息冒号后面的端口号就是对集群外暴露的访问接口
#NodePort范围在 30000-32767之间
kubectl get svc -owide集群外部访问
使用集群节点的ip加上暴露的端口就可以访问 tomcat版本太高返回404的解决办法进入tomcat容器把 webapps 目录删除再 把 webapps.dist 重命名为 webapps 即可。 yaml形式
apiVersion: v1
kind: Service
metadata:labels:app: my-tomcatname: my-tomcat # Service 的名称
spec:ports:- port: 8080 #service的虚拟ip对应的端口在集群内网机器可以访问用service的虚拟ip加该端口号访问nodePort: 30001 #Service在宿主主机上映射的外网访问端口端口范围必须在30000~32767protocol: TCPport: 80 # Service 暴露的端口targetPort: 8080 # 被暴露的 Pod 的容器端口一般与pod内部容器暴露的端口一致selector:app: my-tomcattype: NodePort # Service 类型可以是 ClusterIP、NodePort、LoadBalancer 等 3.6 存储
Volume
Volume指的是存储卷包含可被Pod中容器访问的数据目录。容器中的文件在磁盘上是临时存放的当容器崩溃时文件会丢失同事无法在多个Pod中共享文件通过使用存储卷可以解决这问题。
kubernetes 支持很多类型的卷。Pod可以同时使用任意数目的卷类型。临时卷类型的生命周期与Pod相同但持久卷可以比Pod的存活期长。当Pod不再存在时kubernetes 也会销毁临时卷不过kubernetes 不会销毁永久卷。对于给定的Pod中任何类型的卷在容器重启期间数据都不会丢失。
卷的核心就是一个目录其中可能存有数据Pod中的容器可以访问该目录中的数据。所采用的不同卷类型将决定该目录如何形成的、使用何种介质保存数据以及目录中存放的东西。常见有confingMap、emptyDir、local、nfs、secret等。
ConfingMap可以将配置文件以键值对的形式保存到ConfigMap中并且可以在Pod中以文件或环境变量的形式使用。ConfigMap可以用来存储不敏感的配置信息如应用程序的配置文件。EmptyDir是一个空目录可以在Pod用来存储临时数据当Pod删除时该目录也会删除。Local将本地文件系统的目录或文件映射到Pod中的一个Volume中可以用来在Pod中共享文件或数据。NFS将网络上的一个或多个NFS共享目录挂载到Pod中的Volume中可以用来在多个Pod之间共享数据。Secret将敏感信息以密文的形式保存到Secret中并且可以在Pod中以文件或环境变量的形式使用。Secret可以用来存储敏感信息如用户的密码、证书等。
使用方式 使用卷时, 在 .spec.volumes 字段中设置为 Pod 提供的卷并在 .spec.containers[*].volumeMounts 字段中声明卷在容器中的挂载位置。 容器中的进程看到的文件系统视图是由它们的容器镜像的初始内 容以及挂载在容器中的卷如果定义了的话所组成的。 其中根文件系统同容器镜像的内容相吻合。 任何在该文件系统下的写入操作如果被允许的话都会影响接下来容器中进程访问文件系统时所看 到的内容。 搭建nfs文件系统
nfs(network filesystem ): 网络文件存储系统
安装nfs-server
# 在每个机器。yum install -y nfs-utils# 在master 执行以下命令echo /nfs/data/ *(insecure,rw,sync,no_root_squash) /etc/exports# 执行以下命令启动 nfs 服务;创建共享目录mkdir -p /nfs/data # 在master执行10systemctl enable rpcbindsystemctl enable nfs-serversystemctl start rpcbindsystemctl start nfs-server# 使配置生效exportfs -r #检查配置是否生效exportfsapiVersion: apps/v1
kind: Deployment
metadata:labels:app: nginx-pv-demoname: nginx-pv-demo
spec:replicas: 2selector:matchLabels:app: nginx-pv-demotemplate:metadata:labels:app: nginx-pv-demospec:containers:- image: nginxname: nginxvolumeMounts:- name: htmlmountPath: /usr/share/nginx/htmlvolumes:- name: htmlnfs:server: 192.168.23.201path: /nfs/data/nginx-pv测试通过实现挂载 PV PVC 基本使用 静态供应示例
创建PV池
#nfs主节点1
mkdir -p /nfs/data/01
mkdir -p /nfs/data/02
mkdir -p /nfs/data/03创建PV
apiVersion: v1
kind: PersistentVolume
metadata:name: pv01-10m
spec:capacity:storage: 10MaccessModes:- ReadWriteManystorageClassName: nfsnfs:path: /nfs/data/01server: 192.168.23.201
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv02-1gi
spec:capacity:storage: 1GiaccessModes:- ReadWriteManystorageClassName: nfsnfs:path: /nfs/data/02server: 192.168.23.201
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv03-3gi
spec:capacity:storage: 3GiaccessModes:- ReadWriteManystorageClassName: nfsnfs:path: /nfs/data/03server: 192.168.23.201创建PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: nginx-pvc
spec:accessModes:- ReadWriteManyresources:requests:storage: 200MistorageClassName: nfs自动分配1G的 创建Pod绑定PVC
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: nginx-deploy-pvcname: nginx-deploy-pvc
spec:replicas: 2selector:matchLabels:app: nginx-deploy-pvctemplate:metadata:labels:app: nginx-deploy-pvcspec:containers:- image: nginxname: nginxvolumeMounts:- name: htmlmountPath: /usr/share/nginx/htmlvolumes:- name: htmlpersistentVolumeClaim:claimName: nginx-pvc动态供应 3.7 配置
ConfigMap
在 Kubernetes 中ConfigMap 是一种用于存储非敏感信息的 Kubernetes 对象。它用于存储配置 数据如键值对、整个配置文件或 JSON 数据等。ConfigMap 通常用于容器镜像中的配置文件、命令 行参数和环境变量等。
ConfigMap 可以通过三种方式进行配置数据的注入
环境变量注入将配置数据注入到 Pod 中的容器环境变量中。配置文件注入将配置数据注入到 Pod 中的容器文件系统中容器可以读取这些文件。命令行参数注入将配置数据注入到容器的命令行参数中。
优点
避免了硬编码将配置数据与应用代码分离。便于维护和更新可以单独修改 ConfigMap 而不需要重新构建镜像。可以通过多种方式注入配置数据更加灵活。可以通过 Kubernetes 的自动化机制对 ConfigMap 进行版本控制和回滚。ConfigMap 可以被多个 Pod 共享减少了配置数据的重复存储。
定义 ConfigMap
基本操作 # 查看 configmap$ kubectl get configmap/cm# 查看详细$ kubectl describe configmap/cm my-config# 删除 cm$ kubectl delete cm my-config命令行创建
可以使用kubectl create configmap命令来创建configmap具体命令如下 kubectl create configmap my-config --from-literalkey1value1 --from
literalkey2value2通过配置文件创建推荐
可以通过创建YAML文件的方式来定义configmap的内容。例如创建一个名为 内容如下 然后使用kubectl apply -f命令来创建configmap。
通过文件创建: echo-n admin ./usernameecho -n 123456 ./passwordkubectl create configmap myconfigmap --from-file./username --from-file./password通过文件夹创建
可以将多个配置文件放在同一个文件夹下然后使用如kubectl create configmap命令来创建configmap kubectl create configmap my-config --from-fileconfig-files/这将创建一个名为my-config的configmap其中包含config-files/文件夹下所有的文件内容作为键值对。
通过环境变量创建
可以将环境变量的值转换为configmap。例如使用以下命令将当前环境变量的值转换为configmap kubectl create configmap my-config --from-env-fileenv使用示例 # docker安装redis
docker run -v /data/redis/redis.conf:/etc/redis/redis.conf \
-v /data/redis/data:/data \
-d --name myredis \
-p 6379:6379 \
redis:latest redis-server /etc/redis/redis.conf创建ConfigMap
通过文件的方式创建 #创建redis.conf daemonize yes requirepass root # 创建配置redis保存到k8s的etcdkubectl create cm redis-conf --from-fileredis.conf #查看资源清单kubectl get cm redis-conf -oyaml通过yaml的方式创建
apiVersion: v1kind: ConfigMapmetadata: name: redis-conf data: redis.conf: | maxmemory-policy allkeys-lru requirepass root创建Pod
apiVersion: v1
kind: Pod
metadata:name: redis
spec:containers:- name: redisimage: rediscommand:- redis-server- /redis-master/redis.conf #指的是redis容器内部的位置11# command: [/bin/bash, -ce, tail -f /dev/null]ports:- containerPort: 6379volumeMounts:- mountPath: /dataname: data- mountPath: /redis-mastername: configvolumes:- name: dataemptyDir: {}- name: configconfigMap:name: redis-confitems:- key: redis.confpath: redis.conf测试 kubectl exec -it redis -- redis-cli 127.0.0.1:6379 config get maxmemory-policySecret 定义 Secret
使用命令行创建
可以使用 kubectl create secret 命令来创建 secret例如
kubectl create secret generic my-secret --from-literalusernameadmin --from-literalpasswordadmin123使用 YAML 文件定义 可以创建一个 YAML 文件来定义 Secret 对象例如
apiVersion: v1
kind: Secret
metadata:name: my-secret
type: Opaque
data: username: YWRtaW4 # base64 编码后的用户名 admin password: MWYyZDFlMmU2N2Rm # base64 编码后的密码 1f2d1e2e67df注意: 这个 YAML 文件定义了一个名为 my-secret 的 Secret 对象其中包含了两个 base64 编码后的 key-value 对username 和 password。 使用文件创建:
echo -n admin ./username
echo -n 123456 ./password
kubectl create secret generic mysecret --from-file./username --from-file./password通过环境变量创建
可以将环境变量的值转换为secret。例如使用以下命令将当前环境变量的值转换为secret
kubectl create secret generic my-config --from-env-fileenv使用示例从私有docker仓库拉取镜像 docker pull registry.cn-hangzhou.aliyuncs.com/fox666/tulingmall-product:0.0.5无法从私有镜像仓库拉取镜像抛出如下错误 解决方案使用 docker 的用户信息来生成 secret ##命令格式
kubectl create secret docker-registry myregistrykey \--docker-server你的镜像仓库服务器 \--docker-username你的用户名 \--docker-password你的密码 \--docker-email你的邮箱地址kubectl create secret docker-registry myregistrykey --docker-serverregistry.cn-hangzhou.aliyuncs.com --docker-usernamefox666 --docker-passwordxxx在创建 Pod 的时候通过imagePullSecrets来引用刚创建的myregistrykey
apiVersion: v1
kind: Pod
metadata:name: tulingmall-product
spec:containers:- name: tulingmall-productimage: registry.cn-hangzhou.aliyuncs.com/fox666/tulingmall-product:0.0.5imagePullSecrets: - name: myregistrykey 3.8 Ingress
Ingress 是一种kubernetes资源类型它允许kubernetes 集群中暴露HTTP和HTTPS服务。通过Ingress你可以将流量路由到不同的服务和端口点而无需使用不同的负载均衡器。Ingress通常使用Ingress Contrller实现它是一个运行在kubernetes 集群中的负载均衡器它根据Ingress规则下面是一个将所有流量都发送到同一Service的简单Ingress示例 Ingress和Service区别
Ingress和Service都是kubernetes中用于将流量路由到应用的机制但他们是在路由层面上有所不同
Service是kubernetes中抽象的应用程序服务它公开了一个单一的IP地址和端口可以用于在kubernetes集群内部的Pod之间进行流量路由。Ingress是一个kubernetes资源对象它提供了对集群外部路由的规则。Ingress通过一个公共IP地址和端口将流量路由到一个或多个Service。
安装Ingress
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.47.0/deploy/static/provider/baremetal/deploy.yaml#修改镜像vi deploy.yaml#1、将image k8s.gcr.io/ingress-nginx/controller:v0.46.0sha256:52f0058bed0a17ab0fb35628ba97e8d52b5d32299fbc03cc0f6c7b9ff036b61a的值改为如下值registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/ingress-nginx-controller:v0.46.02安装ingress执行如下命令 kubectl apply -f ingress-controller.yaml查看是否安装成功
kubectl get pod,svc -n ingress-nginx -owide使用Ingress 官网地址
https://kubernetes.github.io/ingress-nginx/配置ingress访问规则就是类似配置nginx的代理转发配置让ingress将域名tomcat.tuling.com 转发给后端的my-tomcat服务新建一个文件ingress-tomcat.yaml内容如下
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata: name: web-ingress
spec:rules: - host: tomcat.tuling.com #转发域名http:paths: - pathType: Prefixpath: /backend:service:name: my-tomcatport:number: 8080 #service的端口 执行如下命令生效规则
kubectl apply -f ingress-tomcat.yaml 查看生效的ingress规则
kubectl get ing在访问机器配置hostwin10客户机在目录C:\Windows\System32\drivers\etc在host里增加如 下host(ingress部署的机器ip对应访问的域名) 192.168.65.82 tomcat.tuling.com配置完后直接在客户机浏览器访问http://tomcat.tuling.com:30940能正常访问tomcat。
ServiceIngress总结 4. K8S核心原理
4.1 K8S的网络模型
K8S的网络中主要存在4种类型的通信
同一Pod内的容器间通信各个Pod彼此间的通信Pod和Service间的通信
集群外部流量和Service之间的通信 K8S为Pod和Service资源对象分别使用了各自的专有网络Pod网络由K8S的网络插件配置实现而 Service网络则由K8S集群进行指定。如下图 K8S使用的网络插件需要为每个Pod配置至少一个特定的地址即Pod IP。Pod IP地址实际存在于某个 网卡可以是虚拟机设备上。
而Service的地址却是一个虚拟IP地址没有任何网络接口配置在此地址上它由Kube-proxy借助 iptables规则或ipvs规则重定向到本地端口再将其调度到后端的Pod对象。Service的IP地址是集群提 供服务的接口也称为Cluster IP。
Pod网络和IP由K8S的网络插件负责配置和管理具体使用的网络地址可以在管理配置网络插件时进行 指定如10.244.0.0/16网络。而Cluster网络和IP是由K8S集群负责配置和管理如10.96.0.0/12网 络。 从上图进行总结起来一个K8S集群包含是三个网络。
节点网络各主机Master、Node、ETCD等自身所属的网络地址配置在主机的网络接口用于各主机之间的通信又称为节点网络。Pod网络专用于Pod资源对象的网络它是一个虚拟网络用于为各Pod对象设定IP地址等网络参数其地址配置在Pod中容器的网络接口上。Pod网络需要借助kubenet插件或CNI插件实现。Service网络专用于Service资源对象的网络它也是一个虚拟网络用于为K8S集群之中的Service配置IP地址但是该地址不会配置在任何主机或容器的网络接口上而是通过Node上的kube-proxy配置为iptables或ipvs规则从而将发往该地址的所有流量调度到后端的各Pod对象之上。
4.2 K8S的工作流程
用K8S部署Nginx的过程中K8S内部各组件是如何协同工作的 我们在master节点执行一条命令要master部署一个nginx应用(kubectl create deployment nginx --imagenginx)
1. 这条命令首先发到master节点的网关api server这是matser的唯一入口
2. api server将命令请求交给controller mannager进行控制
3. controller mannager 进行应用部署解析
4. controller mannager 会生成一次部署信息并通过api server将信息存入etcd存储中
5. scheduler调度器通过api server从etcd存储中拿到要部署的应用开始调度看哪个节点有资源适合部署
6. scheduler把计算出来的调度信息通过api server再放到etcd中
7. 每一个node节点的监控组件kubelet随时和master保持联系给api-server发送请求不断获取最新数据拿到master节点存储在etcd中的部署信息
8. 假设node2的kubelet拿到部署信息显示他自己节点要部署某某应用
9. kubelet就自己run一个应用在当前机器上并随时给master汇报当前应用的状态信息
10. node和master也是通过master的api-server组件联系的
11. 每一个机器上的kube-proxy能知道集群的所有网络只要node访问别人或者别人访问node
12. node上的kube
proxy网络代理自动计算进行流量转发4.3 k8s架构原理六连问
K8S 是一个基于容器技术的分布式集群管理系统。既然是个分布式系统那势必有多个 Node 节点物理主机或虚拟机它们共同组成一个分布式集群并且这些节点中会有一个 Master 节点由它来统一管理Node 节点。
如图所示
问题一主节点和工作节点是如何通信的呢
首先Master 节点启动时会运行一个 kube-apiserver 进程它提供了集群管理的 API 接口是集群内各个功能模块之间数据交互和通信的中心枢纽并且它也提供了完备的集群安全机制。
在 Node 节点上使用 K8S 中的 kubelet 组件在每个 Node 节点上都会运行一个 kubelet 进程它负责向 Master 汇报自身节点的运行情况如 Node 节点的注册、终止、定时上报健康状况等以及接收 Master发出的命令创建相应 Pod。
在 K8S 中Pod 是最基本的操作单元它与 docker 的容器有略微的不同因为 Pod 可能包含一个或多个容器可以是 docker 容器这些内部的容器是共享网络资源的即可以通过 localhost 进行相互访问。关于 Pod 内是如何做到网络共享的每个 Pod 启动内部都会启动一个 pause 容器google的一个镜像它使用默认的网络模式而其他容器的网络都设置给它以此来完成网络的共享问题。
如图所示 问题二Master 是如何将 Pod 调度到指定的 Node 上的
该工作由 kube-scheduler 来完成整个调度过程通过执行一些列复杂的算法最终为每个 Pod 计算出一个最佳的目标 Node该过程由 kube-scheduler 进程自动完成。常见的有轮询调度RR。当然也有可能我们需要将 Pod 调度到一个指定的 Node 上我们可以通过节点的标签Label和 Pod 的 nodeSelector 属性的相互匹配来达到指定的效果。
如图所示 问题三各节点、Pod 的信息都是统一维护在哪里的由谁来维护
从上面的 Pod 调度的角度看我们得有一个存储中心用来存储各节点资源使用情况、健康状态、以及各Pod 的基本信息等这样 Pod 的调度来能正常进行。
在 K8S 中采用 etcd 组件 作为一个高可用强一致性的存储仓库该组件可以内置在 K8S 中也可以外部搭建供 K8S 使用。
集群上的所有配置信息都存储在了 etcd为了考虑各个组件的相对独立以及整体的维护性对于这些存储数据的增、删、改、查统一由 kube-apiserver 来进行调用apiserver 也提供了 REST 的支持不仅对各个内部组件提供服务外还对集群外部用户暴露服务。 外部用户可以通过 REST 接口或者 kubectl 命令行工具进行集群管理其内在都是与 apiserver 进行通信。
如图所示 问题四外部用户如何访问集群内运行的 Pod
前面讲了外部用户如何管理 K8S而我们更关心的是内部运行的 Pod 如何对外访问。使用过Docker 的同学应该知道如果使用 bridge 模式在容器创建时都会分配一个虚拟 IP该 IP 外部是没法访问到的我们需要做一层端口映射将容器内端口与宿主机端口进行映射绑定这样外部通过访问宿主机的指定端口就可以访问到内部容器端口了。
那么K8S 的外部访问是否也是这样实现的答案是否定的K8S 中情况要复杂一些。因为上面讲 的 Docker 是单机模式下的而且一个容器对外就暴露一个服务。在分布式集群下一个服务往往由多个Application 提供用来分担访问压力而且这些 Application 可能会分布在多个节点上这样又涉及到了跨主机的通信。
这里K8S 引入了 Service 的概念将多个相同的 Pod 包装成一个完整的 service 对外提供服务至于获取到这些相同的 Pod每个 Pod 启动时都会设置 labels 属性在 Service 中我们通过选择器 Selector选择具有相同 Name 标签属性的 Pod作为整体服务并将服务信息通过 Apiserver 存入 etcd 中该工作由Service Controller 来完成。同时每个节点上会启动一个 kube-proxy 进程由它来负责服务地址到 Pod地址的代理以及负载均衡等工作。
如图所示
问题五Pod 如何动态扩容和缩放
既然知道了服务是由 Pod 组成的那么服务的扩容也就意味着 Pod 的扩容。通俗点讲就是在需要时将Pod 复制多份在不需要后将 Pod 缩减至指定份数。K8S 中通过 Replication Controller 来进行管理为每个 Pod 设置一个期望的副本数当实际副本数与期望不符时就动态的进行数量调整以达到期望值。期望数值可以由我们手动更新或自动扩容代理来完成。
如图所示 问题六各个组件之间是如何相互协作的
最后讲一下 kube-controller-manager 这个进程的作用。我们知道了 ectd 是作为集群数据的存储中心apiserver 是管理数据中心作为其他进程与数据中心通信的桥梁。而 Service Controller、Replication Controller 这些统一交由 kube-controller-manager 来管理kube-controller-manager 作为一个守护进程每个 Controller 都是一个控制循环通过 apiserver 监视集群的共享状态并尝试将实际状态与期望不符的进行改变。关于 Controllermanager 中还包含了 Node 节点控制器Node Controller、资源配额管控制器ResourceQuota Controller、命名空间控制器Namespace Controller等。
如图所示