背景
传统部署时代: 早期,是直接将应用程序部署在物理机上,无法对应用程序进行资源限制,如果有多个应用,就会出现资源分配的问题,比如一个应用占据大量资源,使用其他应用性能下降,一种解决方案是单个应用放在单个服务器上,这样的话,虽然做到了资源隔离,但是如果一个应用程序资源利用率不高的时候,剩余的资源又无法分配各其他应用程序,而且物理服务器的维护成本变得很高。
虚拟化部署时代: 作为解决方案,引入了虚拟化功能,它允许您在单个物理服务器的 CPU 上运行多个虚拟机VM。虚拟化功能允许应用程序在 VM 之间隔离,并提供安全级别,因为一个应用程序的信息不能被另一应用程序自由地访问。
容器部署时代: 容器类似于 VM,但是它们具有轻量级的隔离属性,可以在应用程序之间共享操作系统OS。因此,容器被认为是目前最轻量级的。容器与 VM 类似,具有自己的文件系统、CPU、内存、进程空间等。由于它们与基础架构分离,因此可以跨云和 OS 分发进行移植。而在容器时代,Docker容器引擎是最流行的一个。
Kubernetes 为你提供了一个可弹性运行分布式系统 的框架。 Kubernetes 会满足你的扩展要求、故障转移你的应用、提供部署模式 等
k8s提供的功能有:
服务发现和负载均衡 使用ip或者dns名称暴露容器ip,让service发现,当service流量过大的时候,会负载均衡到这些容器中
存储编排 允许自动挂载选择的存储系统
自动部署和回滚 通过更改期望状态,就能够实现容器的自动部署和历史版本回滚
自动完成装箱计算 在用户提供了容器需要的资源的基础上,k8s根据容器实际情况分配资源,以最佳方式利用资源
自我修复 k8s 可以重新启动失败的容器,或者替换容器,或者杀死不响应的容器
秘钥和配置管理 Kubernetes 允许你存储和管理敏感信息,例如密码、OAuth 令牌和 ssh 密钥。 你可以在不重建容器镜像的情况下部署和更新密钥和应用程序配置,也无需在堆栈配置中暴露密钥
核心组件
APIServer
系统管理指令的统一入口,担负着统揽全局的重任,任何对资源的增删改查都得交给它后才能交给etcd
功能:
对外提供restful的管理接口,方便对资源对象的增删改查
配置k8s资源对象,将资源对象的当前状态与期望状态存储在etcd中,供其他组件使用,除了etcd,k8s没有其他的持久化结点
系统日志收集,并且提供api供访问
scheduler
在可用的工作结点列表通过算法选取一个结点与待调度的pod进行绑定
调度算法:
首先经历一系列的Predicates判断这个pod能不能在我这个结点上运行,下面列举在default算法中可用的Predicates
PodFitsHostPorts: 查看pod容器需要用的宿主机端口是否有冲突
podFitsResources: 检查结点上的资源是否够用,就是检测结点已有pod对资源的需求量+待调度的pod资源需求量 是否超过工作结点的容量
NoDiskConfict: 检查容器挂在的卷是否有冲突,只对特定的容器卷有效,因为这些容器卷有它们自己的挂载规则,比如禁止两个pod共享同一个容器卷
NoVolumeZoneConfict: 检查pod的挂载卷的zone限制是否与node对应的zone-lable相匹配
MatchNodeSelector: 检查工作结点的lables属性是否和pod的结点标签选择器是否一致
hostname: 如果在pod中指定了宿主机,那么将会调度他到指定的宿主机结点上运行
经历了上述硬性筛选之后,顺利过关的工作结点就会来到打分流程,下面列举打分策略:
LeastRequestedPriority: 计算原则是尽可能的将pod调度到资源占用比小的结点上
BalanceResourceAllocation: 调度时尽可能选取cpu和内存利用率相近的结点
SelectorSpreadPriority: 对于相同的service的pod在节点上尽可能的分散
NodeAffinityPriority: 根据用户指定pod的工作结点亲和性进行打分
ImageLocalityPriorite: 根据pod需要的镜像进行打分,pod需要的镜像大小和越大(pod可以运行多个容器),打分越高
最后计算加权和,看哪个工作结点分高
controller manager
管理k8s中的各种控制器,确保这些资源永远保持在用户所预期的状态
controller manager 控制pod与工作结点等资源正常运行的本质,就是靠这些控制器定时对pod,工作结点等资源进行检查,然后判断实际状态是否与期望状态一直,不一致的话则会通知apiserver进行增删改.
服务端点控制: **检测pod与service之间的对应关系是否正常,**保证始终运行在用户所期望的状态
副本管理控制器: 保证实际副本数量与期望数量一致
垃圾回收控制器: 删除处于终止状态pod的信息,不是删除容器哦
结点控制器: 检查工作结点是否可用,工作结点通过kubelet定时发送数据给master结点,如果在一段时间内没有发送,则认为工作结点不可以工作
资源配额控制器: 对一个namespace 的资源进行配置
kubelet
kubelet是工作结点中最重要的进程,负责创建和管理容器,还有容器和镜像的垃圾回收
kube-proxy
实现服务发现与负载均衡,在后端pod的ip发生变化的时候,也能察觉到,并且维护着service与pod之间的对应关系,将发往service的流量正确的导向pod, 可以通过防火墙或者ipvs实现
etcd
主要用于分布式系统中数据一致性的问题,服务发现
核心组件协作流程
创建pod
我们通过kubectl发起一个创建pod的请求后,kubectl会先检查命令是否正确,然后解析命令生成的pod资源文件发送给apiserver,apiserver收到请求后,进行用户认证,授权,和资源配额控制,验证通过后,apiserver调用etcd的存储接口在后台数据库创建一个pod对象,scheduler通过apiserve监听到需要创建pod,然后从etcd获取可用工作结点列表和待调度的pod,在发现有待调度的pod且有工作结点的时候,会通过筛选结点,给结点打分,选出最优结点,然后调用apiserver提供的api在etcd中创建一个binding对象,描述在一个工作结点绑定运行的所有pod信息,kubelet监听到apiserver上要创建pod,然后在本地创建对应的pod
基础环境部署
前期准备
用了三台虚拟机,都是centos7
192.168.100.3 master结点
192.168.100.4 work1结点
192.168.100.5 work2结点
修改hostname
1 2 3 4 5 6 7 8 # master上执行 hostnamectl set-hostname master exec bash # work1 上执行 hostnamectl set-hostname work1 exec bash # work2 上执行 hostnamectl set-hostname work2
配置hosts文件(所有结点)
1 2 3 4 5 6 7 # 两台机器都执行 cat >> /etc/hosts << EOF 192.168.100.3 master 192.168.100.4 work1 192.168.100.5 work2 192.168.100.3 cluster-endpoint EOF
配置ssh互信(所有结点)
1 2 3 4 5 6 7 # 所有机器都执行 ssh-keygen # 一直回车得到秘钥 ssh-copy-id -i ~/.ssh/id_rsa.pub root@master ssh-copy-id -i ~/.ssh/id_rsa.pub root@work1 ssh-copy-id -i ~/.ssh/id_rsa.pub root@work2
设置时间同步(所有结点)
1 2 3 4 yum install chrony -y systemctl start chronyd systemctl enable chronyd chronyc sources
关闭防火墙(所有结点)
1 2 systemctl stop firewalld systemctl disable firewalld
关闭交换区(所有结点)
1 2 swapoff -a sed -ri 's/.*swap.*/#&/' /etc/fstab
禁用seninux(所有结点)
1 2 setenforce 0 sed -i 's/^SELINUX=enforcing$/SELINUX=disabled/' /etc/selinux/config
允许 iptables 检查桥接流量(所有结点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 modprobe br_netfilter cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf overlay br_netfilter EOF modprobe overlay modprobe br_netfilter # 设置所需的 sysctl 参数,参数在重新启动后保持不变 cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-iptables = 1 net.bridge.bridge-nf-call-ip6tables = 1 net.ipv4.ip_forward = 1 EOF # 应用 sysctl 参数而不重新启动 sudo sysctl --system
安装docker(所有结点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 # 配置yum源 cd /etc/yum.repos.d ; mkdir bak; mv CentOS-Base.repo bak/ wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo # wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-8.repo (这个是centos8的源) # 安装yum-config-manager配置工具 yum -y install yum-utils # 设置yum源 yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 安装docker-ce版本 yum install -y docker-ce # 启动 systemctl start docker # 开机自启 systemctl enable docker # 查看版本号 docker --version # Docker镜像源设置 cat >/etc/docker/daemon.json<<EOF { "registry-mirrors": ["http://hub-mirror.c.163.com"] } EOF # 加载 systemctl reload docker
配置k8s源(所有结点)
1 2 3 4 5 6 7 cat > /etc/yum.repos.d/kubernetes.repo << EOF [k8s] name=k8s enabled=1 gpgcheck=0 baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/ EOF
将 sandbox_image 镜像源设置为阿里云 google_containers 镜像源(一条一条命令来哦)(所有结点)
1 2 3 4 5 6 7 # 导出默认配置,config.toml这个文件默认是不存在的 containerd config default > /etc/containerd/config.toml grep sandbox_image /etc/containerd/config.toml # 把 sandbox_image = "registry.k8s.io/pause:3.6" (不同版本对应的可能不同) # 改成 sandbox_image = "registry.aliyuncs.com/google_containers/pause/pause:3.6" sed -i "s#registry.k8s.io/pause#registry.aliyuncs.com/google_containers/pause#g" /etc/containerd/config.toml grep sandbox_image /etc/containerd/config.toml
配置container国内镜像源
1 2 3 4 5 6 7 8 9 10 11 12 13 # 打开配置文件 vim /etc/containerd/config.toml # 改成下面这种格式 [plugins."io.containerd.grpc.v1.cri".registry.mirrors] [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] endpoint = ["https://o13jbvy6.mirror.aliyuncs.com"] # 重启containerd systemctl daemon-reload systemctl restart containerd systemctl status containerd
得一层一层来,https://blog.csdn.net/cyxinda/article/details/124999938 (可以参考这个博客)
配置 containerd cgroup 驱动程序 systemd(所有结点)
1 2 sed -i 's#SystemdCgroup = false#SystemdCgroup = true#g' /etc/containerd/config.toml systemctl restart containerd
安装 kubeadm,kubelet 和 kubectl(所有结点)
1 2 3 4 5 6 7 8 # 不指定版本就是最新版本,当前最新版就是1.24.1 yum install -y kubelet-1.24.1 kubeadm-1.24.1 kubectl-1.24.1 --disableexcludes=kubernetes # disableexcludes=kubernetes:禁掉除了这个kubernetes之外的别的仓库 # 设置为开机自启并现在立刻启动服务 --now:立刻启动服务 systemctl enable --now kubelet # 查看状态,这里需要等待一段时间再查看服务状态,启动会有点慢 systemctl status kubelet
使用kubeadm初始化集群(master)
下载好镜像
1 2 3 4 5 6 7 docker pull registry.aliyuncs.com/google_containers/kube-apiserver:v1.24.1 docker pull registry.aliyuncs.com/google_containers/kube-controller-manager:v1.24.1 docker pull registry.aliyuncs.com/google_containers/kube-scheduler:v1.24.1 docker pull registry.aliyuncs.com/google_containers/kube-proxy:v1.24.1 docker pull registry.aliyuncs.com/google_containers/pause:3.7 docker pull registry.aliyuncs.com/google_containers/etcd:3.5.3-0 docker pull registry.aliyuncs.com/google_containers/coredns:v1.8.6
设置kubectl 自动补全
1 2 3 4 5 # 来到家目录 cd ~ echo 'source <(kubectl completion bash)' >>~/.bashrc # 重新加载bash exec bash
初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 kubeadm init \ --apiserver-advertise-address=192.168.100.3 \ --image-repository registry.aliyuncs.com/google_containers \ --control-plane-endpoint=cluster-endpoint \ --kubernetes-version v1.24.1 \ --service-cidr=10.1.0.0/16 \ --pod-network-cidr=10.244.0.0/16 \ --v=5 # –image-repository string: 这个用于指定从什么位置来拉取镜像(1.13版本才有的),默认值是k8s.gcr.io,我们将其指定为国内镜像地址:registry.aliyuncs.com/google_containers # –kubernetes-version string: 指定kubenets版本号,默认值是stable-1,会导致从https://dl.k8s.io/release/stable-1.txt下载最新的版本号,我们可以将其指定为固定版本(v1.22.1)来跳过网络请求。 # –apiserver-advertise-address 指明用 Master 的哪个 interface 与 Cluster 的其他节点通信。如果 Master 有多个 interface,建议明确指定,如果不指定,kubeadm 会自动选择有默认网关的 interface。这里的ip为master节点ip,记得更换。 # –pod-network-cidr 指定 Pod 网络的范围。Kubernetes 支持多种网络方案,而且不同网络方案对 –pod-network-cidr有自己的要求,这里设置为10.244.0.0/16 是因为我们将使用 flannel 网络方案,必须设置成这个 CIDR。 # --control-plane-endpoint cluster-endpoint 是映射到该 IP 的自定义 DNS 名称,这里配置hosts映射:192.168.0.113 cluster-endpoint。 这将允许你将 --control-plane-endpoint=cluster-endpoint 传递给 kubeadm init,并将相同的 DNS 名称传递给 kubeadm join 。 稍后你可以修改 cluster-endpoint 以指向高可用性方案中的负载均衡器的地址。
执行提示出来的命令
1 2 3 mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config
此时master结点还是notready的状态
需要安装一个网络插件
安装网络插件(master结点)
1 2 3 4 #提前下载好镜像 docker pull quay.io/coreos/flannel:v0.14.0 # 这里可能不成功,最好是下载好这个文件然后上传到虚拟机,在执行这个命令 kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
1 2 # 查看所有pod的状态 kubectl get pods -A
当所有pod都在running的时候,主节点就准备好了
work结点加入集群
1 2 # 在master结点上面执行下面命令得到加入主节点的命令 kubeadm token create --print-join-command
1 2 #在work1结点中输入这个命令 kubeadm join cluster-endpoint:6443 --token 6z9ttd.gi5caxzuargatfy9 --discovery-token-ca-cert-hash sha256:05c589ead7b690359fc1a6208be07390ce40894939c29d025e04477442bfc4d8
等待一段时间后,在主节点中查看所有结点是否都准备好了
安装dashboard
1 2 kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.6.0/aio/deploy/recommended.yaml # 可能会下载不下来,建议本地用梯子下载好后,传到虚拟机上
需要等到kubernetes-dashboard的所有pod都在running后才能访问哦,有可能会出现镜像拉取失败
通过端口访问
1 2 3 4 5 6 7 8 9 10 11 kubectl edit svc kubernetes-dashboard -n kubernetes-dashboard #上面命令会打开一个文件,我们需要修改一些配置 # 输入 /type 搜索到目标位置 # type: ClusterIP 将这个东西变成 # type: NodePort # 要注意yaml的语法哦,空格 # 然后保存退出 # 看dashboard 运行在哪个端口 kubectl get svc -A |grep kubernetes-dashboard
如果在Google浏览器里面输入 https://ip :端口显示不安全,而且不让进去的话,就在键盘直接输入 thisisunsafe 然后就可以进去了
创建账户
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 cat >ServiceAccount.yaml<<EOF apiVersion: v1 kind: ServiceAccount metadata: name: admin-user namespace: kubernetes-dashboard --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: admin-user roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: admin-user namespace: kubernetes-dashboard EOF kubectl apply -f ServiceAccount.yaml
获取token
1 kubectl -n kubernetes-dashboard create token admin-user
安装ingress
1 kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.7.1/deploy/static/provider/cloud/deploy.yaml
nfs安装
我们如果使用本地容器卷的模式,当主机挂掉了之后,k8s转移pod到其他主机上,但是其他主机上没有这个容器卷,因此我们要整一个共享的存储空间
环境准备
1 yum install -y nfs-utils # 所有结点安装
主节点
1 2 3 4 5 6 7 8 # nfs主节点 echo "/nfs/data/ *(insecure,rw,sync,no_root_squash)" > /etc/exports mkdir -p /nfs/data systemctl enable rpcbind --now systemctl enable nfs-server --now # 配置生效 exportfs -r
工作结点
1 2 3 4 5 6 7 8 showmount -e 192.168.100.3 # 执行以下命令挂载 nfs 服务器上的共享目录到本机路径 /root/nfsmount mkdir -p /nfs/data mount -t nfs 192.168.100.3:/nfs/data /nfs/data # 写入一个测试文件 echo "hello nfs server" > /nfs/data/test.txt
创建资源YAML详解
定义k8s的资源对象配置文件yaml一般包含四个部分
apiVersion 这个表示版本 不同的api版本创建的资源对象可能不一样
kind 资源类型,表示你要创建什么样的资源,一般有 Pod Deployment Service Ingress 等等
metadata 表示元数据,资源名称,所属namespace 标签
spec 资源规范字段,比如用什么容器,重启策略
创建pod
总结
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 apiVersion: v1 kind: Pod metadata: name: string namespace: string labels: - name: string annotations: - name: string spec: containers: - name: string image: string imagePullPolicy: [Always | Never | IfNotPresent ] command: [string ] args: [string ] workingDir: string volumeMounts: - name: string mountPath: string readOnly: boolean ports: - name: string containerPort: int hostPort: int protocol: string env: - name: string value: string resources: limits: cpu: string memory: string requests: cpu: string memory: string livenessProbe: exec: command: [string ] httpGet: path: string port: number host: string scheme: string HttpHeaders: - name: string value: string tcpSocket: port: number initialDelaySeconds: 0 timeoutSeconds: 0 periodSeconds: 0 successThreshold: 0 failureThreshold: 0 securityContext: privileged:false restartPolicy: [Always | Never | OnFailure ] nodeSelector: obeject imagePullSecrets: - name: string hostNetwork:false volumes: - name: string emptyDir: {} hostPath: string path: string secret: scretname: string items: - key: string path: string configMap: name: string items: - key: string
尝试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 apiVersion: v1 kind: Pod metadata: name: my-nginx namespace: default labels: run: nginx spec: containers: - name: mynginx image: nginx imagePullPolicy: IfNotPresent command: [/docker-entrypoint.sh ] args: [ "nginx" , "-g" , "daemon off;" ] workingDir: / volumeMounts: - name: html mountPath: /usr/share/nginx/html ports: - name: web containerPort: 80 hostPort: 80 protocol: TCP env: - name: djm value: nb resources: limits: cpu: 1 memory: 200Mi livenessProbe: httpGet: path: / port: 80 host: localhost initialDelaySeconds: 1 timeoutSeconds: 1 periodSeconds: 10 restartPolicy: Always volumes: - name: html nfs: server: 192.168 .100 .3 path: /nfs/data/nginx
检测我们的健康检查生效,失败的原因是没有文件,我们需要在宿主机上放一个文件,在宿主机上
验证环境变量
创建Deployment
总结
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 apiVersion: apps/v1 kind: Deployment metadata: name: demo namespace: default labels: app: demo version: stable spec: replicas: 1 revisionHistoryLimit: 3 selector: matchLabels: app: demo version: stable strategy: rollingUpdate: maxSurge: 30 % maxUnavailable: 30 % type: RollingUpdate template: metadata: annotations: sidecar.istio.io/inject: "false" labels: app: demo version: stable spec: containers: - name: demo image: demo:v1 imagePullPolicy: IfNotPresent resources: limits: cpu: 300m memory: 500Mi requests: cpu: 100m memory: 100Mi livenessProbe: httpGet: path: /healthCheck port: 8080 scheme: HTTP initialDelaySeconds: 30 timeoutSeconds: 5 periodSeconds: 30 successThreshold: 1 failureThreshold: 5 readinessProbe: httpGet: path: /healthCheck port: 8080 scheme: HTTP initialDelaySeconds: 30 timeoutSeconds: 5 periodSeconds: 10 successThreshold: 1 failureThreshold: 5 ports: - name: http containerPort: 8080 protocol: TCP imagePullSecrets: - name: harbor-certification affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: beta.kubernetes.io/arch operator: In values: - amd64
尝试
删除
删除单个工作结点
master 结点上执行
1 2 3 4 5 6 7 8 # 让资源对象不会往这个结点上调度 kubectl cordon nodename # 在master结点上执行,驱逐一个结点,最好在这这个命令之前把在这个结点上的pod删掉 kubectl drain nodename # 删除节点 kubectl delete node nodename # 如果没有删掉结点上的pod,其实这个时候结点上的pod在其他地方还能访问到,那些规则还存在,等过一段时间后,k8s发现这个结点删除了,会让这些pod转移到其他机器上
node结点上执行(为了下次加入集群方便,不报错)(这个时候所有的iptables的规则,以及虚拟网卡,还都存在,我们必须手动清除)
1 2 3 # 清除旧的信息 kubeadm reset -f # 能重启一下最好
删除整个集群
1 2 3 4 5 6 7 8 9 10 11 12 13 14 # 删除所有结点 kubectl delete node --all # 清理主节点 kubeadm reset -f rm -fr ~/.kube/ /etc/kubernetes/* /var/lib/etcd/* # 清理工作结点 kubeadm reset -f # 重启一下,或者手动删除iptables规则和网卡 # 如果不想使用了,可以把服务也停了 systemctl enable kubelet --now
删除定义好的那些规则(这个是全部删除)
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
额外补充
自动补全
1 2 3 4 5 6 7 8 9 10 # kubectl source <(kubectl completion bash) kubectl completion bash >/etc/bash_completion.d/kubectl # source <(helm completion bash)# helm completion bash >/etc/bash_completion.d/helm # crictl (containered) source <(crictl completion bash) crictl completion bash >/etc/bash_completion.d/crictl
不会写yaml配置文件怎么办
我们只要记得kubectl的命令可以,可以用这个命令来生成yaml文件(不过会有冗余内容哦
1 2 3 4 5 6 7 8 # 创建一个depolyment资源对象的yaml kubectl create deploy mydep --image=nginx --replicas 5 -o yaml --dry-run=client > depoly.yaml # 创建一个service 的 yaml kubectl expose deploy mydep --port=8080 --target-port=80 --type=NodePort -o yaml --dry-run=client > depoly.yaml # 如果当前资源对象已经存在(这种方式产生的冗余东西会更多) kubectl get deploy mydep -o wide > depoly.yaml kubectl get svc mydep -o wide > depoly.yaml
pod创建流程
kubectl 一次pod创建流程中,各个组件干的活:
kubectl 将命令解析成生成创建pod的参数,通过apiserver提供的接口传递过去
apiserver 收到后,先进行上下文和pod元数据验证两者的namespace是否匹配,不匹配则创建失败,成功则将一些系统元数据(创建时间,uid)注入到pod中,然后检测元数据中系统必须项是否存在,如果为空则抛出异常,终止创建.如果一切顺利,在etcd中持久化pod信息,然后将创建pod的工作交给kube-scheduler和kubelet
kube-scheduler 根据待调度的pod以及可用的工作结点根据算法选取一个最优的绑定策略,然后告诉apiserve选取哪个结点部署pod,apiserve收到后发送请求给结点上的kubelet
kubelet 根据要求只会容器运行时创建容器就可以了