锅从天上来
IP:
0关注数
0粉丝数
0获得的赞
工作年
编辑资料
链接我:

创作·182

全部
问答
动态
项目
学习
专栏
锅从天上来

【Kubernetes】控制器Daemonset

一、简介1.1、概念DaemonSet控制器能够确保k8s集群所有的节点都运行一个相同的pod副本当向k8s集群中增加node节点时,这个node节点也会自动创建一个pod副本当node节点从集群移除,这些pod也会自动删除;删除Daemonset也会删除它们创建的pod。1.2、原理如何管理Pod?daemonset的控制器会监听kuberntes的daemonset对象、pod对象、node对象,这些被监听的对象之变动,就会触发syncLoop循环让kubernetes集群朝着daemonset对象描述的状态进行演进。1.3、应用场景在集群的每个节点上运行存储,比如:glusterd 或 ceph。在每个节点上运行日志收集组件,比如:flunentd 、 logstash、filebeat等。在每个节点上运行监控组件,比如:Prometheus、 Node Exporter 、collectd等。1.4、DaemonSet 与 Deployment 的区别Deployment 部署的副本 Pod 会分布在各个 Node 上,每个 Node 都可能运行好几个副本。DaemonSet 的不同之处在于:每个 Node 上最多只能运行一个副本。二、DaemonSet资源清单文件编写技巧2.1、查看定义Daemonset资源需要的字段有哪些[root@master ~]# kubectl explain ds KIND: DaemonSet VERSION: apps/v1 DESCRIPTION: DaemonSet represents the configuration of a daemon set. FIELDS: apiVersion <string> # 当前资源使用的api版本,跟VERSION: apps/v1保持一致 kind <string> # 资源类型,跟KIND: DaemonSet保持一致 metadata <Object> # 元数据,定义DaemonSet名字的 spec <Object> # 定义容器的 status <Object> # 状态信息,不能改2.2、查看DaemonSet的spec字段如何定义[root@master ~]# kubectl explain ds.spec KIND: DaemonSet VERSION: apps/v1 RESOURCE: spec <Object> DESCRIPTION: The desired behavior of this daemon set. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status DaemonSetSpec is the specification of a daemon set. FIELDS: minReadySeconds <integer> # 当新的pod启动几秒种后,再kill掉旧的pod。 revisionHistoryLimit <integer> # 历史版本 selector <Object> -required- # 用于匹配pod的标签选择器 template <Object> -required- # 定义Pod的模板,基于这个模板定义的所有pod是一样的 updateStrategy <Object> # daemonset的升级策略2.3、查看DaemonSet的spec.template字段如何定义对于template而言,其内部定义的就是pod,pod模板是一个独立的对象[root@master ~]# kubectl explain ds.spec.template KIND: DaemonSet VERSION: apps/v1 RESOURCE: template <Object> DESCRIPTION: ...... FIELDS: metadata <Object> spec <Object> 三、DaemonSet使用案例:部署日志收集组件fluentd3.1、导入镜像把fluentd-2-5-1.tar.gz上传到工作节点node01、node02上,解压.特别注意: 因为我们安装的k8s版本是1.25,那就需要按照文档步骤ctr -n=k8s.io images import导出镜像,如果k8s版本是1.24之前的,可以用docker load -i解压,视频里用的docker load -i,现在我们课程安装更新到了k8s1.25,所以导出镜像需要用ctr -n=k8s.io images import[root@master 13]# scp fluentd_2_5_1.tar.gz root@10.32.1.147:/root/package fluentd_2_5_1.tar.gz 100% 142MB 28.0MB/s 00:05 [root@master 13]# scp fluentd_2_5_1.tar.gz root@10.32.1.148:/root/package fluentd_2_5_1.tar.gz 100% 142MB 52.1MB/s 00:02 [root@master 13]#[root@node01 package]# ctr -n=k8s.io images import fluentd_2_5_1.tar.gz unpacking docker.io/xianchao/fluentd:v2.5.1 (sha256:3baf02875b273fe6f675710d0f25ea9374b94d6704c334c75e854f8465a777a9)...done [root@node02 package]# ctr -n=k8s.io images import fluentd_2_5_1.tar.gz unpacking docker.io/xianchao/fluentd:v2.5.1 (sha256:3baf02875b273fe6f675710d0f25ea9374b94d6704c334c75e854f8465a777a9)...done3.2、编写资源清单并创建资源[root@master 13]# cat daemonset.yaml apiVersion: apps/v1 kind: DaemonSet metadata: labels: k8s-app: fluentd-logging name: fluentd-elasticsearch namespace: kube-system spec: selector: matchLabels: name: fluentd-elasticsearch template: metadata: name: fluentd labels: name: fluentd-elasticsearch spec: tolerations: - key: node-role.kubernetes.io/master effect: NoSchedule containers: - name: fluentd-elasticsearch image: xianchao/fluentd:v2.5.1 resources: limits: memory: 500Mi requests: cpu: 100m memory: 200Mi volumeMounts: - name: varlog mountPath: /var/log - name: varlibdockercontainers mountPath: /var/lib/docker/containers readOnly: true terminationGracePeriodSeconds: 30 volumes: - name: varlog hostPath: path: /var/log - name: varlibdockercontainers hostPath: path: /var/lib/docker/containers[root@master 13]# kubectl apply -f daemonset.yaml daemonset.apps/fluentd-elasticsearch created [root@master 13]# kubectl get ds -n kube-system NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE calico-node 3 3 2 3 2 kubernetes.io/os=linux 24d fluentd-elasticsearch 2 2 2 2 2 <none> 30s kube-proxy 3 3 3 3 3 kubernetes.io/os=linux 24d [root@master 13]# kubectl get pods -n kube-system -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES fluentd-elasticsearch-27xqk 1/1 Running 0 100s 10.244.140.113 node02 <none> <none> fluentd-elasticsearch-zzzlr 1/1 Running 0 100s 10.244.196.163 node01 <none> <none>通过上面可以看到在k8s的三个节点均创建了fluentd这个pod。pod的名字是由控制器的名字-随机数组成的。3.3、清单详细说明[root@master 13]# cat daemonset.yaml apiVersion: apps/v1 # DaemonSet使用的api版本 kind: DaemonSet # 资源类型 metadata: labels: k8s-app: fluentd-logging # 资源具有的标签 name: fluentd-elasticsearch # 资源的名字 namespace: kube-system # 资源所在的名称空间 spec: selector: # 标签选择器 matchLabels: name: fluentd-elasticsearch template: metadata: name: fluentd labels: # 基于这回模板定义的pod具有的标签 name: fluentd-elasticsearch spec: tolerations: # 定义容忍度 - key: node-role.kubernetes.io/master effect: NoSchedule containers: # 定义容器 - name: fluentd-elasticsearch image: xianchao/fluentd:v2.5.1 resources: # 资源配额 limits: memory: 500Mi requests: cpu: 100m memory: 200Mi volumeMounts: - name: varlog mountPath: /var/log # 将varlog卷挂载到容器中指定挂载点/var/log - name: varlibdockercontainers mountPath: /var/lib/docker/containers # 将varlibdockercontainers卷容器中指定挂载点/var/lib/docker/containers readOnly: true # 挂载目录是只读权限 terminationGracePeriodSeconds: 30 # 优雅的关闭服务 volumes: - name: varlog hostPath: path: /var/log # 基于本地目录创建一个卷 - name: varlibdockercontainers hostPath: path: /var/lib/docker/containers # 基于本地目录创建一个卷四、Daemonset管理pod:滚动更新4.1、查看daemonset的滚动更新策略[root@master 13]# kubectl explain ds.spec.updateStrategy KIND: DaemonSet VERSION: apps/v1 RESOURCE: updateStrategy <Object> DESCRIPTION: An update strategy to replace existing DaemonSet pods with new pods. DaemonSetUpdateStrategy is a struct used to control the update strategy for a DaemonSet. FIELDS: rollingUpdate <Object> Rolling update config params. Present only if type = "RollingUpdate". type <string> Type of daemon set update. Can be "RollingUpdate" or "OnDelete". Default is RollingUpdate. Possible enum values: - `"OnDelete"` Replace the old daemons only when it's killed - `"RollingUpdate"` Replace the old daemons by new ones using rolling update i.e replace them on each node one after the other.4.2、查看rollingUpdate支持的更新策略[root@master 13]# kubectl explain ds.spec.updateStrategy.rollingUpdate KIND: DaemonSet VERSION: apps/v1 RESOURCE: rollingUpdate <Object> DESCRIPTION: Rolling update config params. Present only if type = "RollingUpdate". Spec to control the desired behavior of daemon set rolling update. FIELDS: maxSurge <string> maxUnavailable <string> # rollingUpdate更新策略只支持maxUnavailabe,先删除再更新 # 因为我们不支持一个节点运行两个pod,因此需要先删除一个,再更新一个。4.3、更新演示kubectl set image daemonsets fluentd-elasticsearch fluentd-elasticsearch=ikubernetes/filebeat:5.6.6-alpine -n kube-system这个镜像启动pod会有问题,主要是演示daemonset如何在命令行更新pod
0
0
0
浏览量2015
锅从天上来

【Kubernetes】七层代理Ingress

一、回顾四层代理Service1.1、在k8s中为什么要做负载均衡?pod漂移问题,可以理解成pod ip是变化的。k8s具有强大的副本控制能力,能保证再任意副本pod挂掉时,自动从其他机器启动一个新的,还可以动态库容。通俗地说,这个pod可能任何时刻出现在任何节点上,也可能在任何时刻死在任何节点上。那么自然随着pod的创建和销毁,pod ip是变化的,如何把这个动态的pod ip暴露出去?这里借助k8s的色弱ice机制,service可以以标签形式选定一组带指定标签的pod,并监控和自动负载他们的pod ip,那么我们向外暴露只暴露了service ip就行了。这里就是NodePort模式:即在每个节点上开启一个端口,然后转发到内部pod ip上。svc域名组成:svc名称.svc所在名称空间.svc.cluster.local这个只能在集群内部访问,即只能在pod里面去访问这个域名,因为svc域名是由cordns解析的,物理机用的dns可以通过cat /etc/resolv.conf查看,这俩个dns不是同一个网段的。1.2、Service存在的问题Service可以通过标签选择器找到它所关联的pod,但是属于四层代理,只能基于ip和端口代理。# svc创建后,会对应创建endpoint # ENDPOINTS 存的就是这个service对应的后端pod所对应的ip+port [root@master ~]# k get ep -n kube-system NAME ENDPOINTS AGE kube-dns 10.244.140.72:53,10.244.140.75:53,10.244.140.72:53 + 3 more... 43d metrics-server 10.244.140.71:4443 42d # 这里svc和pod的ip怎么保存到防火墙规则里面? 通过kube-proxy实现,保存到ipvs规则里面 # 通过ipvsadm -Ln可以看到Service的type类型有很多,如NodePort、ClusterIp、LoadBalancer、Externalname,如果Service想要被k8s集群外部访问,需要用NodePort类型,但这有以下几个问题:+++++++++++++++1、nodeport会在物理机映射一个端口,绑定到物理机上,导致每个服务都要映射一个端口,端口过多,维护困难。2、service底层使用的是iptables或者ipvs,仅支持四层代理,无法基于https协议做代理。+++++++++++++++1.3、四层负载和七层负载的区别四层负载:基于ip和端口的负载均衡。在三层负载基础上通过发布三层的ip地址(VIP)然后加上四层的端口号,来决定哪些流量需要做负载均衡;对需要处理的流量进行NAT处理,然后转发至后台服务器,并记录 下这个TCP或者UDP的流量是由那台服务器处理的,后续这个连接的所有流量都同样转发到同一台服务器处理。七层负载: 基于虚拟的URL或主机IP的负载均衡,在四层的基础上,再考虑应用层的特征,比如同一个web服务器的负载均衡,除了根据VIP加80端口辨别是否需要处理的流量,还可以根据七层的URL、浏览器类别、语言来决定是否需要进行负载均衡。举个例子,如果你的Web服务器分成两组,一组是中文语言的,一组是英文语言的,那么七层负载均衡就可以当用户来访问你的域名时,自动辨别用户语言,然后选择对应的语言服务器组进行负载均衡处理。四层负载均衡工作在传输层,七层负载均衡工作在应用层OSI七层模型:二、Ingress和Ingress Controller介绍2.1、Ingress官网定义Ingress可以把进入到集群内部的请求转发到集群中的一些服务上,从而可以把服务映射到集群外部。Ingress能把集群内Service配置成外网能够访问的URL、流量负载均衡,提供基于域名访问的虚拟主机等。简单理解原来需要修改nginx配置,然后配置各种域名对应哪个service,现在把这个动作抽象出来,变成一个Ingress对象,你可以用yaml创建,每次不要去改nginx了,直接改yaml然后创建/更新就行了。Ingress总结Ingress是k8s中的资源,主要是管理ingress-controller这个代理的配置文件。Ingress Controller解决的是“nginx的处理方式”,它通过与kubernetes api交互,动态感知集群中Ingress规则变化,动态读取,然后按照自己的模板生成一段nginx配置,再写到nginx pod里面,最后reload一下2.2、Ingress ControllerIngress Controller是一个七层负载均衡调度器,客户端的请求先到达这个七层负载均衡调度器,由七层负载均衡器在反向代理到后端pod。常见的七层负载均衡器有nginx、traefik,以我们熟悉的nginx为例,假如请求到达nginx,会通过upstream反向代理到后端pod应用,但是后端pod的ip地址是一直在变化的,因此在后端pod前需要加一个service,这个service只是起到分组的作用,那么我们upstream只需要填写service地址即可。Ingress-controller里面封装就是nginx,直接在物理机上装个nginx,为啥还弄个Ingress-controller?Nginx:nginx配置文件一改动,你还需要手动reload一下才可以生效,但是如果用ingress-controller封装的nginx,你ingress维护配置,ingress创建好之后,会自动的把配置文件传到ingress-controller这个pod里,会自动进行reload,然后配置就生效了。2.3、使用Ingress Controller代理k8s内部pod流程步骤:【1】部署Ingress Controller,这里ingress controller 使用的是nginx【2】创建pod应用,可以通过控制器创建pod【3】创建service,用来分组pod【4】创建Ingress http,测试通过http访问权限【5】创建Ingress https,测试通过https访问应用2.4、总结1、Ingress Controller结合Ingress 定义的规则生成配置,然后动态更新ingress-controller里的Nginx 或者trafik负载均衡器,并刷新使配置生效,来达到服务自动发现的作用。2、Ingress 则是定义规则,通过它定义某个域名的请求过来之后转发到集群中指定的 Service。它可以通过 Yaml 文件定义,可以给一个或多个 Service 定义一个或多个 Ingress 规则。三、Ingress Controller高可用Ingress Controller 是集群流量的接入层,对它做高可用非常重要,可以基于keepalive实现nginx-ingress-controller高可用:Ingress-controler根据deployment+nodeselector+pod反亲和性方式部署在k8s指定的俩个work节点,nginx-ingress-controller这个pod共享宿主机ip,然后通过keepalive+nginx实现nginx-ingress-controller高可用。https://github.com/kubernetes/ingress-nginxhttps://github.com/kubernetes/ingress-nginx/tree/main/deploy/static/provider/baremetal3.1、部署ingress-nginx-controller【1】在工作节点上传镜像文件,然后解压。[root@node01 package]# ctr -n=k8s.io images import ingress-nginx-controllerv1.1.0.tar.gz [root@node01 package]# ctr -n=k8s.io images import kube-webhook-certgen-v1.1.0.tar.gz [root@node02 package]# ctr -n=k8s.io images import ingress-nginx-controllerv1.1.0.tar.gz [root@node02 package]# ctr -n=k8s.io images import kube-webhook-certgen-v1.1.0.tar.gz【2】运行yaml文件[root@master 17]# kubectl apply -f ingress-deploy.yaml [root@master 17]# kubectl get pod -n ingress-nginx -owide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES ingress-nginx-admission-create-2zhnk 0/1 Completed 0 6m18s 10.244.196.130 node01 <none> <none> ingress-nginx-admission-patch-htsrd 0/1 Completed 1 6m18s 10.244.196.129 node01 <none> <none> ingress-nginx-controller-64bdc78c96-6c9c6 1/1 Running 0 41s 10.32.1.148 node01 <none> <none> ingress-nginx-controller-64bdc78c96-fpvlf 1/1 Running 0 6m18s 10.32.1.149 node02 <none> <none> # 如果ingress-nginx-controller-xx的pod出现问题,用kubectl logs -f 或者kubectl describe去排查,我出现问题的原因是节点上的80端口被占用了ingress-nginx-controller–里面封装的就是nginx七层代理。这里的pod使用的是宿主机的ip。3.2、基于keepalive和nginx实现ingress-nginx-controller高可用【1】nginx主备安装在工作节点执行yum install epel-release nginx keepalived nginx-mod-stream -y[root@node01 ~]# yum install epel-release nginx keepalived nginx-mod-stream -y [root@node02 ~]# yum install epel-release nginx keepalived nginx-mod-stream -y修改nginx配置文件。主备一样[root@node01 ~]# cat /etc/nginx/nginx.conf user nginx; worker_processes auto; error_log /var/log/nginx/error.log; pid /run/nginx.pid; include /usr/share/nginx/modules/*.conf; events { worker_connections 1024; } # 四层负载均衡,为两台Master apiserver组件提供负载均衡 stream { log_format main '$remote_addr $upstream_addr - [$time_local] $status $upstream_bytes_sent'; access_log /var/log/nginx/k8s-access.log main; upstream k8s-ingress-controller { server 10.32.1.148:80 weight=5 max_fails=3 fail_timeout=30s; # 修改成自己工作节点的ip server 10.32.1.149:80 weight=5 max_fails=3 fail_timeout=30s; # 修改成自己工作节点的ip } server { listen 30080; proxy_pass k8s-ingress-controller; } } http { log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; include /etc/nginx/mime.types; default_type application/octet-stream; }备注:server 反向服务地址和端口weight 权重max_fails 失败多少次,认为主机已挂掉,则踢出fail_timeout 踢出后重新探测时间nginx监听端口变成大于30000的端口,比方说30080,这样访问域名:30080就可以了,必须是满足大于30000以上,才能代理ingress-controller【2】keepalive配置主配置[root@node01 ~]# cat /etc/keepalived/keepalived.conf global_defs { notification_email { acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc smtp_server 127.0.0.1 smtp_connect_timeout 30 router_id NGINX_MASTER } vrrp_script check_nginx { script "/etc/keepalived/check_nginx.sh" } vrrp_instance VI_1 { state MASTER interface ens32 # 修改为实际网卡名 virtual_router_id 51 # VRRP 路由 ID实例,每个实例是唯一的 priority 100 # 优先级,备服务器设置 90 advert_int 1 # 指定VRRP 心跳包通告间隔时间,默认1秒 authentication { auth_type PASS auth_pass 1111 } # 虚拟IP virtual_ipaddress { 10.32.1.155/24 } track_script { check_nginx } } 备配置 (和主配置的区别就是优先级 priority 和state)[root@node02 package]# cat /etc/keepalived/keepalived.conf global_defs { notification_email { acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc smtp_server 127.0.0.1 smtp_connect_timeout 30 router_id NGINX_MASTER } vrrp_script check_nginx { script "/etc/keepalived/check_nginx.sh" } vrrp_instance VI_1 { state BACKUP interface ens32 # 修改为实际网卡名 virtual_router_id 51 # VRRP 路由 ID实例,每个实例是唯一的 priority 90 # 优先级,备服务器设置 90 advert_int 1 # 指定VRRP 心跳包通告间隔时间,默认1秒 authentication { auth_type PASS auth_pass 1111 } # 虚拟IP virtual_ipaddress { 10.32.1.155/24 } track_script { check_nginx } }#vrrp_script:指定检查nginx工作状态脚本(根据nginx状态判断是否故障转移)#virtual_ipaddress:虚拟IP(VIP)【3】判断nginx是否存活[root@node01 keepalived]# cat check_nginx.sh #!/bin/bash #1、判断Nginx是否存活 counter=$(ps -ef |grep nginx | grep sbin | egrep -cv "grep|$$" ) if [ $counter -eq 0 ]; then #2、如果不存活则尝试启动Nginx service nginx start sleep 2 #3、等待2秒后再次获取一次Nginx状态 counter=$(ps -ef |grep nginx | grep sbin | egrep -cv "grep|$$" ) #4、再次进行判断,如Nginx还不存活则停止Keepalived,让地址进行漂移 if [ $counter -eq 0 ]; then service keepalived stop fi fi [root@node01 keepalived]# chmod +x /etc/keepalived/check_nginx.sh # 注:keepalived根据脚本返回状态码(0为工作正常,非0不正常)判断是否故障转移。【4】启动服务node01和node02都要操作 systemctl daemon-reload systemctl enable nginx keepalived systemctl start nginx systemctl start keepalived【5】测试vip是否绑定成功node01是主,上面会有vip【6】测试keepalived停掉node01上的keepalived。Vip会漂移到node02上[root@node01 keepalived]# service keepalived stop Redirecting to /bin/systemctl stop keepalived.service You have mail in /var/spool/mail/rootsystemctl status keepalived -l检测keepalived是否正常3.3、测试Ingress HTTP 代理k8s内部pod【1】部署后端tomcat服务[root@master 17]# cat ingress-demo.yaml apiVersion: v1 kind: Service metadata: name: tomcat namespace: default spec: selector: app: tomcat release: canary ports: - name: http targetPort: 8080 port: 8080 - name: ajp targetPort: 8009 port: 8009 --- apiVersion: apps/v1 kind: Deployment metadata: name: tomcat-deploy namespace: default spec: replicas: 2 selector: matchLabels: app: tomcat release: canary template: metadata: labels: app: tomcat release: canary spec: containers: - name: tomcat image: tomcat:8.5.34-jre8-alpine imagePullPolicy: IfNotPresent ports: - name: http containerPort: 8080 name: ajp containerPort: 8009 # 更新资源清单yaml文件 [root@master 17]# kubectl apply -f ingress-demo.yaml service/tomcat created deployment.apps/tomcat-deploy created[root@master 17]# k get pod|grep tomcat tomcat-deploy-64d6489dd9-vmx79 1/1 Running 0 3d1h tomcat-deploy-64d6489dd9-vngw9 1/1 Running 0 3d1h [root@master 17]# k get svc|grep tomcat tomcat ClusterIP 10.109.171.118 <none> 8080/TCP,8009/TCP 3d1h [root@master 17]# k describe svc tomcat Name: tomcat Namespace: default Labels: <none> Annotations: <none> Selector: app=tomcat,release=canary Type: ClusterIP IP Family Policy: SingleStack IP Families: IPv4 IP: 10.109.171.118 IPs: 10.109.171.118 Port: http 8080/TCP TargetPort: 8080/TCP Endpoints: 10.244.140.87:8080,10.244.196.166:8080 Port: ajp 8009/TCP TargetPort: 8009/TCP Endpoints: 10.244.140.87:8009,10.244.196.166:8009 Session Affinity: None Events: <none>【2】编写ingress规则[root@master 17]# cat ingress-myapp.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ingress-myapp namespace: default spec: ingressClassName: nginx rules: - host: tomcat.lucky.com http: paths: - backend: service: name: tomcat port: number: 8080 path: / pathType: Prefix [root@master 17]# kubectl apply -f ingress-myapp.yaml ingress.networking.k8s.io/ingress-myapp created如果出现以下报错:解决办法:kubectl delete -A ValidatingWebhookConfiguration ingress-nginx-admission# 查看ingress-myapp的详细信息 [root@master 17]# kubectl describe ingress ingress-myapp Name: ingress-myapp Labels: <none> Namespace: default Address: 10.32.1.148,10.32.1.149 Ingress Class: nginx Default backend: <default> Rules: Host Path Backends ---- ---- -------- tomcat.lucky.com / tomcat:8080 (10.244.140.87:8080,10.244.196.166:8080) Annotations: <none> Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Sync 2m23s (x2 over 2m48s) nginx-ingress-controller Scheduled for sync Normal Sync 2m23s (x2 over 2m48s) nginx-ingress-controller Scheduled for sync【3】测试访问修改电脑本地的host文件,增加如下一行,下面的ip是vip10.32.1.155 tomcat.lucky.com浏览器访问tomcat.lucky.com:30080,出现如下页面:代理流程:tomcat.lucky.com:30080——>10.32.1.155:30080——>10.32.1.148/149:80——>svc:tomcat:8080——>tomcat-deploy浏览器访问tomcat.lucky.com:30080,通过域名解析,会访问10.32.1.155:3008010.32.1.155是VIP,通过虚拟ip访问nginx,此时的vip是在node01主机上,所有走的是node01节点的nginx,即10.32.1.148:30080根据nginx配置文件规则,会随机转发到 10.32.1.149:80或10.32.1.148:80根据ingress规则,会将流量转达对应svc(tomcat:8080)svc会将流量转发到后端对应的pod上3.4、测试Ingress HTTPS代理k8s内部pod【1】构建TLS站点1、在控制节点上,创建证书[root@master ~]# openssl genrsa -out tls.key 2048 Generating RSA private key, 2048 bit long modulus ....+++ ...............................................................................+++ e is 65537 (0x10001) [root@master ~]# openssl req -new -x509 -key tls.key -out tls.crt -subj /C=CN/ST=Beijing/L=Beijing/O=DevOps/CN=hejin.lucky.com 2、在控制节点上,生成secret[root@master ~]# kubectl create secret tls tomcat-ingress-secret --cert=tls.crt --key=tls.key secret/tomcat-ingress-secret created3、查看secret[root@master ~]# kubectl get secret NAME TYPE DATA AGE mysecret Opaque 2 22d mysql-password Opaque 1 22d tomcat-ingress-secret kubernetes.io/tls 2 24s4、查看tomcat-ingress-secret详细信息[root@master ~]# kubectl get secret NAME TYPE DATA AGE mysecret Opaque 2 22d mysql-password Opaque 1 22d tomcat-ingress-secret kubernetes.io/tls 2 24s [root@master ~]# kubectl describe secret tomcat-ingress-secret Name: tomcat-ingress-secret Namespace: default Labels: <none> Annotations: <none> Type: kubernetes.io/tls Data ==== tls.key: 1679 bytes tls.crt: 1289 bytes【2】创建IngressIngress规则可以参考官方:https://kubernetes.io/zh/docs/concepts/services-networking/ingress/[root@master 17]# cat ingress-tomcat-tls.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ingress-tomcat-tls namespace: default spec: ingressClassName: nginx tls: - hosts: - hejin.lucky.com secretName: tomcat-ingress-secret rules: - host: hejin.lucky.com http: paths: - path: / pathType: Prefix backend: service: name: tomcat port: number: 8080更新yaml文件[root@master 17]# kubectl delete -f ingress-myapp.yaml [root@master 17]# kubectl apply -f ingress-tomcat-tls.yaml【3】修改电脑的hosts文件打开C:\Windows\System32\drivers\etc目录,找到hosts文件,如下:...... 10.32.1.155 tomcat.lucky.com 10.32.1.155 hejin.lucky.com ......使用浏览器访问:http://hejin.lucky.com/四、同一个k8s搭建多套Ingress-controller更新中。。。
0
0
0
浏览量2019
锅从天上来

K8S(十)—容器探针

容器探针(probe)probe 是由 kubelet 对容器执行的定期诊断。 要执行诊断,kubelet 既可以在容器内执行代码,也可以发出一个网络请求。检查机制使用探针来检查容器有四种不同的方法。 每个探针都必须准确定义为这四种机制中的一种:exec在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断成功。grpc使用 gRPC 执行一个远程过程调用。 目标应该实现 gRPC 健康检查。 如果响应的状态是 “SERVING”,则认为诊断成功。httpGet对容器的 IP 地址上指定端口和路径执行 HTTP GET 请求。如果响应的状态码大于等于 200 且小于 400,则诊断被认为是成功的。tcpSocket对容器的 IP 地址上的指定端口执行 TCP 检查。如果端口打开,则诊断被认为是成功的。 如果远程系统(容器)在打开连接后立即将其关闭,这算作是健康的。注意: 和其他机制不同,exec 探针的实现涉及每次执行时创建/复制多个进程。 因此,在集群中具有较高 pod 密度、较低的 initialDelaySeconds 和 periodSeconds 时长的时候, 配置任何使用 exec 机制的探针可能会增加节点的 CPU 负载。 这种场景下,请考虑使用其他探针机制以避免额外的开销。探测结果每次探测都将获得以下三种结果之一:Success(成功)容器通过了诊断。Failure(失败)容器未通过诊断。Unknown(未知)诊断失败,因此不会采取任何行动。探测类型针对运行中的容器,kubelet 可以选择是否执行以下三种探针,以及如何针对探测结果作出反应:livenessProbe指示容器是否正在运行。如果存活态探测失败,则 kubelet 会杀死容器, 并且容器将根据其重启策略决定未来。如果容器不提供存活探针, 则默认状态为 Success。readinessProbe指示容器是否准备好为请求提供服务。如果就绪态探测失败, 端点控制器将从与 Pod 匹配的所有服务的端点列表中删除该 Pod 的 IP 地址。 初始延迟之前的就绪态的状态值默认为 Failure。 如果容器不提供就绪态探针,则默认状态为 Success。startupProbe指示容器中的应用是否已经启动。如果提供了启动探针,则所有其他探针都会被 禁用,直到此探针成功为止。如果启动探测失败,kubelet 将杀死容器, 而容器依其重启策略进行重启。 如果容器没有提供启动探测,则默认状态为 Success。如欲了解如何设置存活态、就绪态和启动探针的进一步细节, 可以参阅配置存活态、就绪态和启动探针。何时该使用存活态探针?如果容器中的进程能够在遇到问题或不健康的情况下自行崩溃,则不一定需要存活态探针; kubelet 将根据 Pod 的 restartPolicy 自动执行修复操作。如果你希望容器在探测失败时被杀死并重新启动,那么请指定一个存活态探针, 并指定 restartPolicy 为 “Always” 或 “OnFailure”。何时该使用就绪态探针?如果要仅在探测成功时才开始向 Pod 发送请求流量,请指定就绪态探针。 在这种情况下,就绪态探针可能与存活态探针相同,但是规约中的就绪态探针的存在意味着 Pod 将在启动阶段不接收任何数据,并且只有在探针探测成功后才开始接收数据。如果你希望容器能够自行进入维护状态,也可以指定一个就绪态探针, 检查某个特定于就绪态的因此不同于存活态探测的端点。如果你的应用程序对后端服务有严格的依赖性,你可以同时实现存活态和就绪态探针。 当应用程序本身是健康的,存活态探针检测通过后,就绪态探针会额外检查每个所需的后端服务是否可用。 这可以帮助你避免将流量导向只能返回错误信息的 Pod。如果你的容器需要在启动期间加载大型数据、配置文件或执行迁移, 你可以使用启动探针。 然而,如果你想区分已经失败的应用和仍在处理其启动数据的应用,你可能更倾向于使用就绪探针。说明:请注意,如果你只是想在 Pod 被删除时能够排空请求,则不一定需要使用就绪态探针; 在删除 Pod 时,Pod 会自动将自身置于未就绪状态,无论就绪态探针是否存在。 等待 Pod 中的容器停止期间,Pod 会一直处于未就绪状态。何时该使用启动探针?对于所包含的容器需要较长时间才能启动就绪的 Pod 而言,启动探针是有用的。 你不再需要配置一个较长的存活态探测时间间隔,只需要设置另一个独立的配置选定, 对启动期间的容器执行探测,从而允许使用远远超出存活态时间间隔所允许的时长。如果你的容器启动时间通常超出 initialDelaySeconds + failureThreshold × periodSeconds 总值,你应该设置一个启动探测,对存活态探针所使用的同一端点执行检查。 periodSeconds 的默认值是 10 秒。你应该将其 failureThreshold 设置得足够高, 以便容器有充足的时间完成启动,并且避免更改存活态探针所使用的默认值。 这一设置有助于减少死锁状况的发生。使用exec拉取yaml文件[root@k8smaster probe]# wget https://k8s.io/examples/pods/probe/exec-liveness.yaml --no-check-certificate从网上拉取文件创建 Pod:kubectl apply -f https://k8s.io/examples/pods/probe/exec-liveness.yaml[root@k8smaster probe]# cat exec-liveness.yaml apiVersion: v1 kind: Pod metadata: labels: test: liveness name: liveness-exec spec: containers: - name: liveness image: busybox args: - /bin/sh - -c - touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600 livenessProbe: exec: command: - cat - /tmp/healthy initialDelaySeconds: 5 periodSeconds: 5 可能拉取镜像失败,修改下本地创建[root@k8smaster probe]# ls exec-liveness.yaml [root@k8smaster probe]# kubectl apply -f exec-liveness.yaml pod/liveness-exec created在 30 秒内,查看 Pod 的事件:kubectl describe pod liveness-execType Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 83s default-scheduler Successfully assigned default/liveness-exec to k8snode2 Normal Pulled 80s kubelet Successfully pulled image "busybox" in 2.029247825s Normal Created 80s kubelet Created container liveness Normal Started 80s kubelet Started container liveness Warning Unhealthy 35s (x3 over 45s) kubelet Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory Normal Killing 35s kubelet Container liveness failed liveness probe, will be restarted Normal Pulling 5s (x2 over 82s) kubelet Pulling image "busybox"看重启次数liveness-exec 1/1 Running 1 2m26s 10.244.185.237 k8snode2 <none> <none> http另外一种类型的存活探测方式是使用 HTTP GET 请求。 下面是一个 Pod 的配置文件,其中运行一个基于 registry.k8s.io/liveness 镜像的容器。pods/probe/http-liveness.yamlapiVersion: v1 kind: Pod metadata: labels: test: liveness name: liveness-http spec: containers: - name: liveness image: registry.k8s.io/liveness args: - /server livenessProbe: httpGet: path: /healthz port: 8080 httpHeaders: - name: Custom-Header value: Awesome initialDelaySeconds: 3 periodSeconds: 3 在这个配置文件中,你可以看到 Pod 也只有一个容器。 periodSeconds 字段指定了 kubelet 每隔 3 秒执行一次存活探测。 initialDelaySeconds 字段告诉 kubelet 在执行第一次探测前应该等待 3 秒。 kubelet 会向容器内运行的服务(服务在监听 8080 端口)发送一个 HTTP GET 请求来执行探测。 如果服务器上 /healthz 路径下的处理程序返回成功代码,则 kubelet 认为容器是健康存活的。 如果处理程序返回失败代码,则 kubelet 会杀死这个容器并将其重启。返回大于或等于 200 并且小于 400 的任何代码都标示成功,其它返回代码都标示失败。你可以访问 server.go阅读服务的源码。 容器存活期间的最开始 10 秒中,/healthz 处理程序返回 200 的状态码。 之后处理程序返回 500 的状态码。http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { duration := time.Now().Sub(started) if duration.Seconds() > 10 { w.WriteHeader(500) w.Write([]byte(fmt.Sprintf("error: %v", duration.Seconds()))) } else { w.WriteHeader(200) w.Write([]byte("ok")) } })kubelet 在容器启动之后 3 秒开始执行健康检测。所以前几次健康检查都是成功的。 但是 10 秒之后,健康检查会失败,并且 kubelet 会杀死容器再重新启动容器。创建一个 Pod 来测试 HTTP 的存活检测:kubectl apply -f https://k8s.io/examples/pods/probe/http-liveness.yaml10 秒之后,通过查看 Pod 事件来确认存活探针已经失败,并且容器被重新启动了。kubectl describe pod liveness-httptcp第三种类型的存活探测是使用 TCP 套接字。 使用这种配置时,kubelet 会尝试在指定端口和容器建立套接字链接。 如果能建立连接,这个容器就被看作是健康的,如果不能则这个容器就被看作是有问题的。pods/probe/tcp-liveness-readiness.yamlapiVersion: v1 kind: Pod metadata: name: goproxy labels: app: goproxy spec: containers: - name: goproxy image: registry.k8s.io/goproxy:0.1 ports: - containerPort: 8080 readinessProbe: tcpSocket: port: 8080 initialDelaySeconds: 5 periodSeconds: 10 livenessProbe: tcpSocket: port: 8080 initialDelaySeconds: 15 periodSeconds: 20如你所见,TCP 检测的配置和 HTTP 检测非常相似。 下面这个例子同时使用就绪和存活探针。kubelet 会在容器启动 5 秒后发送第一个就绪探针。 探针会尝试连接 goproxy 容器的 8080 端口。 如果探测成功,这个 Pod 会被标记为就绪状态,kubelet 将继续每隔 10 秒运行一次探测。除了就绪探针,这个配置包括了一个存活探针。 kubelet 会在容器启动 15 秒后进行第一次存活探测。 与就绪探针类似,存活探针会尝试连接 goproxy 容器的 8080 端口。 如果存活探测失败,容器会被重新启动。kubectl apply -f https://k8s.io/examples/pods/probe/tcp-liveness-readiness.yaml15 秒之后,通过看 Pod 事件来检测存活探针:kubectl describe pod goproxygrpc如果你的应用实现了 gRPC 健康检查协议, kubelet 可以配置为使用该协议来执行应用存活性检查。 你必须启用 GRPCContainerProbe 特性门控 才能配置依赖于 gRPC 的检查机制。这个例子展示了如何配置 Kubernetes 以将其用于应用的存活性检查。 类似地,你可以配置就绪探针和启动探针。下面是一个示例清单:pods/probe/grpc-liveness.yamlapiVersion: v1 kind: Pod metadata: name: etcd-with-grpc spec: containers: - name: etcd image: registry.k8s.io/etcd:3.5.1-0 command: [ "/usr/local/bin/etcd", "--data-dir", "/var/lib/etcd", "--listen-client-urls", "http://0.0.0.0:2379", "--advertise-client-urls", "http://127.0.0.1:2379", "--log-level", "debug"] ports: - containerPort: 2379 livenessProbe: grpc: port: 2379 initialDelaySeconds: 10要使用 gRPC 探针,必须配置 port 属性。 如果要区分不同类型的探针和不同功能的探针,可以使用 service 字段。 你可以将 service 设置为 liveness,并使你的 gRPC 健康检查端点对该请求的响应与将 service 设置为 readiness 时不同。 这使你可以使用相同的端点进行不同类型的容器健康检查而不是监听两个不同的端口。 如果你想指定自己的自定义服务名称并指定探测类型,Kubernetes 项目建议你使用使用一个可以关联服务和探测类型的名称来命名。 例如:myservice-liveness(使用 - 作为分隔符)。说明:与 HTTP 和 TCP 探针不同,gRPC 探测不能使用按名称指定端口, 也不能自定义主机名。配置问题(例如:错误的 port 或 service、未实现健康检查协议) 都被认作是探测失败,这一点与 HTTP 和 TCP 探针类似。kubectl apply -f https://k8s.io/examples/pods/probe/grpc-liveness.yaml15 秒钟之后,查看 Pod 事件确认存活性检查并未失败:kubectl describe pod etcd-with-grpc在 Kubernetes 1.23 之前,gRPC 健康探测通常使用 [grpc-health-probe] 来实现,如博客 [Health checking gRPC servers on Kubernetes**(对 Kubernetes 上的 gRPC 服务器执行健康检查)**所描述。 内置的 gRPC 探针的行为与 grpc-health-probe 所实现的行为类似。 从 grpc-health-probe 迁移到内置探针时,请注意以下差异:内置探针运行时针对的是 Pod 的 IP 地址,不像 grpc-health-probe 那样通常针对 127.0.0.1 执行探测; 请一定配置你的 gRPC 端点使之监听于 Pod 的 IP 地址之上。内置探针不支持任何身份认证参数(例如 -tls)。对于内置的探针而言,不存在错误代码。所有错误都被视作探测失败。如果 ExecProbeTimeout 特性门控被设置为 false,则 grpc-health-probe 不会考虑 timeoutSeconds 设置状态(默认值为 1s), 而内置探针则会在超时时返回失败。使用命名端口对于 HTTP 和 TCP 存活检测可以使用命名的 port(gRPC 探针不支持使用命名端口)。例如:ports: - name: liveness-port containerPort: 8080 hostPort: 8080 livenessProbe: httpGet: path: /healthz port: liveness-port使用启动探针保护慢启动容器有时候,会有一些现有的应用在启动时需要较长的初始化时间。 要这种情况下,若要不影响对死锁作出快速响应的探测,设置存活探测参数是要技巧的。 技巧就是使用相同的命令来设置启动探测,针对 HTTP 或 TCP 检测,可以通过将 failureThreshold * periodSeconds 参数设置为足够长的时间来应对最糟糕情况下的启动时间。这样,前面的例子就变成了:ports: - name: liveness-port containerPort: 8080 hostPort: 8080 livenessProbe: httpGet: path: /healthz port: liveness-port failureThreshold: 1 periodSeconds: 10 startupProbe: httpGet: path: /healthz port: liveness-port failureThreshold: 30 periodSeconds: 10幸亏有启动探测,应用将会有最多 5 分钟(30 * 10 = 300s)的时间来完成其启动过程。 一旦启动探测成功一次,存活探测任务就会接管对容器的探测,对容器死锁作出快速响应。 如果启动探测一直没有成功,容器会在 300 秒后被杀死,并且根据 restartPolicy 来执行进一步处置。定义就绪探针有时候,应用会暂时性地无法为请求提供服务。 例如,应用在启动时可能需要加载大量的数据或配置文件,或是启动后要依赖等待外部服务。 在这种情况下,既不想杀死应用,也不想给它发送请求。 Kubernetes 提供了就绪探针来发现并缓解这些情况。 容器所在 Pod 上报还未就绪的信息,并且不接受通过 Kubernetes Service 的流量。说明:就绪探针在容器的整个生命周期中保持运行状态。注意:存活探针与就绪性探针相互间不等待对方成功。 如果要在执行就绪性探针之前等待,应该使用 initialDelaySeconds 或 startupProbe。就绪探针的配置和存活探针的配置相似。 唯一区别就是要使用 readinessProbe 字段,而不是 livenessProbe 字段。readinessProbe: exec: command: - cat - /tmp/healthy initialDelaySeconds: 5 periodSeconds: 5HTTP 和 TCP 的就绪探针配置也和存活探针的配置完全相同。就绪和存活探测可以在同一个容器上并行使用。 两者共同使用,可以确保流量不会发给还未就绪的容器,当这些探测失败时容器会被重新启动。配置探针Probe 有很多配置字段,可以使用这些字段精确地控制启动、存活和就绪检测的行为:•initialDelaySeconds:容器启动后要等待多少秒后才启动启动、存活和就绪探针。 如果定义了启动探针,则存活探针和就绪探针的延迟将在启动探针已成功之后才开始计算。 如果 periodSeconds 的值大于 initialDelaySeconds,则 initialDelaySeconds 将被忽略。默认是 0 秒,最小值是 0。•periodSeconds:执行探测的时间间隔(单位是秒)。默认是 10 秒。最小值是 1。•timeoutSeconds:探测的超时后等待多少秒。默认值是 1 秒。最小值是 1。•successThreshold:探针在失败后,被视为成功的最小连续成功数。默认值是 1。 存活和启动探测的这个值必须是 1。最小值是 1。•failureThreshold:探针连续失败了 failureThreshold 次之后, Kubernetes 认为总体上检查已失败:容器状态未就绪、不健康、不活跃。 对于启动探针或存活探针而言,如果至少有 failureThreshold 个探针已失败, Kubernetes 会将容器视为不健康并为这个特定的容器触发重启操作。 kubelet 遵循该容器的 terminationGracePeriodSeconds 设置。 对于失败的就绪探针,kubelet 继续运行检查失败的容器,并继续运行更多探针; 因为检查失败,kubelet 将 Pod 的 Ready 状况设置为 false。•terminationGracePeriodSeconds:为 kubelet 配置从为失败的容器触发终止操作到强制容器运行时停止该容器之前等待的宽限时长。 默认值是继承 Pod 级别的 terminationGracePeriodSeconds 值(如果不设置则为 30 秒),最小值为 1。 更多细节请参见探针级别 terminationGracePeriodSeconds。注意:如果就绪态探针的实现不正确,可能会导致容器中进程的数量不断上升。 如果不对其采取措施,很可能导致资源枯竭的状况。HTTP 探测HTTP Probes 允许针对 httpGet 配置额外的字段:•host:连接使用的主机名,默认是 Pod 的 IP。也可以在 HTTP 头中设置 “Host” 来代替。•scheme:用于设置连接主机的方式(HTTP 还是 HTTPS)。默认是 “HTTP”。•path:访问 HTTP 服务的路径。默认值为 “/”。•httpHeaders:请求中自定义的 HTTP 头。HTTP 头字段允许重复。•port:访问容器的端口号或者端口名。如果数字必须在 1~65535 之间。对于 HTTP 探测,kubelet 发送一个 HTTP 请求到指定的端口和路径来执行检测。 除非 httpGet 中的 host 字段设置了,否则 kubelet 默认是给 Pod 的 IP 地址发送探测。 如果 scheme 字段设置为了 HTTPS,kubelet 会跳过证书验证发送 HTTPS 请求。 大多数情况下,不需要设置 host 字段。 这里有个需要设置 host 字段的场景,假设容器监听 127.0.0.1,并且 Pod 的 hostNetwork 字段设置为了 true。那么 httpGet 中的 host 字段应该设置为 127.0.0.1。 可能更常见的情况是如果 Pod 依赖虚拟主机,你不应该设置 host 字段,而是应该在 httpHeaders 中设置 Host。针对 HTTP 探针,kubelet 除了必需的 Host 头部之外还发送两个请求头部字段:•User-Agent:默认值是 kube-probe/1.28,其中 1.28 是 kubelet 的版本号。•Accept:默认值 */*。你可以通过为探测设置 httpHeaders 来重载默认的头部字段值。例如:livenessProbe: httpGet: httpHeaders: - name: Accept value: application/json startupProbe: httpGet: httpHeaders: - name: User-Agent value: MyUserAgent你也可以通过将这些头部字段定义为空值,从请求中去掉这些头部字段。livenessProbe: httpGet: httpHeaders: - name: Accept value: "" startupProbe: httpGet: httpHeaders: - name: User-Agent value: ""TCP 探测对于 TCP 探测而言,kubelet 在节点上(不是在 Pod 里面)发起探测连接, 这意味着你不能在 host 参数上配置服务名称,因为 kubelet 不能解析服务名称。探针层面的 terminationGracePeriodSeconds特性状态: Kubernetes v1.28 [stable]在 1.25 及以上版本中,用户可以指定一个探针层面的 terminationGracePeriodSeconds 作为探针规约的一部分。 当 Pod 层面和探针层面的 terminationGracePeriodSeconds 都已设置,kubelet 将使用探针层面设置的值。当设置 terminationGracePeriodSeconds 时,请注意以下事项:•kubelet 始终优先选用探针级别 terminationGracePeriodSeconds 字段 (如果它存在于 Pod 上)。•如果你已经为现有 Pod 设置了 terminationGracePeriodSeconds 字段并且不再希望使用针对每个探针的终止宽限期,则必须删除现有的这类 Pod。例如:spec: terminationGracePeriodSeconds: 3600 # Pod 级别设置 containers: - name: test image: ... ports: - name: liveness-port containerPort: 8080 hostPort: 8080 livenessProbe: httpGet: path: /healthz port: liveness-port failureThreshold: 1 periodSeconds: 60 # 重载 Pod 级别的 terminationGracePeriodSeconds terminationGracePeriodSeconds: 60 探针层面的 terminationGracePeriodSeconds 不能用于就绪态探针。 这一设置将被 API 服务器拒绝。
0
0
0
浏览量2013
锅从天上来

K8S(四)—pod详解

pod介绍Kubernetes(通常被缩写为K8s)是一个用于自动部署、扩展和管理容器化应用程序的开源容器编排平台。Pod是Kubernetes中最小的可部署和可管理的计算单元。以下是关于Kubernetes中的Pod的详细解释:Pod的概念:1、Pod的定义: Pod是Kubernetes中的最小调度单元,它可以包含一个或多个紧密耦合的容器。这些容器共享相同的网络命名空间、IP地址和端口空间。2、容器的组合: Pod中的容器通常协同工作,它们可以共享存储卷(Volumes)、环境变量等资源。这使得它们能够更容易地共享数据和通信。3、生命周期: Pod是一个短暂的资源,其生命周期由包含的容器决定。当Pod内的所有容器都终止时,Pod也会终止。Pod的特性:1.共享网络命名空间: Pod中的所有容器共享相同的网络命名空间,它们可以通过localhost相互通信,使用相同的IP地址和端口。2.共享存储卷: Pod中的容器可以通过存储卷共享数据。这允许它们之间共享文件系统状态。3.共享进程空间: Pod中的容器可以共享相同的进程空间,这意味着它们可以通过进程间通信进行交互。Pod的配置:1.Pod规约: Pod的规约定义了一个或多个容器的运行规范,包括容器的镜像、环境变量、资源限制等。2.标签(Labels): Pod可以被附上标签,这些标签可以用于选择和过滤Pod,从而进行操作和管理。Pod的控制:1.控制器(Controllers): 控制器是用来确保Pod按照用户定义的规约运行的组件。常见的控制器有Deployment、StatefulSet等。2.调度器(Scheduler): 调度器负责将Pod调度到集群中的节点上,并确保它们按照规约运行。示例 YAML 文件:以下是一个简单的Pod的YAML示例:apiVersion: v1 kind: Pod metadata: name: mypod spec: containers: - name: mycontainer image: nginx:latest这个示例定义了一个Pod,其中包含一个名为mycontainer的容器,该容器使用Nginx的最新镜像。总的来说,Pod是Kubernetes中非常重要的概念,它为容器提供了一个逻辑主机,使得容器可以共享资源并协同工作。 Pod的设计使得在Kubernetes中部署和管理应用程序变得更加灵活和强大。pod启动流程问题1.kubelet是定期主动访问api server知道有哪些pod需要启动,还是scheduler主动去通知kubelet去访问api server的?192.168.2.210[root@k8smaster1 ~]# netstat -anplut|grep kubelet tcp 0 0 127.0.0.1:10248 0.0.0.0:* LISTEN 17335/kubelet tcp 0 0 127.0.0.1:34513 0.0.0.0:* LISTEN 17335/kubelet tcp 0 0 192.168.2.210:43032 192.168.2.210:6443 ESTABLISHED 17335/kubelet tcp6 0 0 :::10250 :::* LISTEN 17335/kubelet 192.168.2.211[root@k8snode1 ~]# netstat -anplut|grep kubelet tcp 0 0 127.0.0.1:10248 0.0.0.0:* LISTEN 25050/kubelet tcp 0 0 127.0.0.1:44939 0.0.0.0:* LISTEN 25050/kubelet tcp 0 0 192.168.2.211:49362 192.168.2.210:6443 ESTABLISHED 25050/kubelet tcp6 0 0 :::10250 :::* LISTEN 25050/kubelet 192.168.2.212[root@k8snode2 ~]# netstat -anpult|grep kubelet tcp 0 0 127.0.0.1:34325 0.0.0.0:* LISTEN 4194/kubelet tcp 0 0 127.0.0.1:10248 0.0.0.0:* LISTEN 4194/kubelet tcp 0 0 192.168.2.212:58678 192.168.2.210:6443 ESTABLISHED 4194/kubelet tcp6 0 0 :::10250 :::* LISTEN 4194/kubelet 2.etcd数据发生了变化,哪些控制器是如何知道的?是其他程序通知的还是,定时去检查的?在Kubernetes中,etcd 是一个分布式的键值存储系统,被用作集群中所有组件共享配置信息和状态的后端存储。当 etcd 中的数据发生变化时,Kubernetes 中的控制器是通过轮询(polling)机制来感知这些变化的,而不是通过事件通知。以下是控制器如何知道 etcd 数据变化的一般流程:    1.轮询机制: Kubernetes中的控制器通过轮询的方式定期查询 etcd,检查与它们关联的对象(例如Pod、Service、ReplicaSet等)的状态是否发生变化。这是一种主动的方式,控制器定期查询 etcd 数据库,看是否有更新。    2.Watch机制: Kubernetes也使用了一种叫做Watch的机制,它允许组件注册在 etcd 上某个特定资源路径上的事件。当 etcd 中的数据发生变化时,相关的Watch事件将被触发,然后组件可以收到这些事件并作出相应的处理。虽然Watch机制用于实现事件驱动,但目前(截至我知识截断日期2022年),Kubernetes控制器主要仍然以轮询为主。    3.Informers: Kubernetes客户端库中提供了Informers的概念,这是一种缓存和事件处理的机制。Informers会定期从 etcd 中获取资源的最新状态,并将其缓存在本地。当本地缓存中的对象状态发生变化时,它可以触发相应的事件,这样控制器可以监听这些事件来感知状态的变化。总的来说,Kubernetes控制器通过定期查询 etcd 数据库,使用Watch机制或者Informers等机制,以轮询方式感知 etcd 中数据的变化。尽管有一些机制支持事件驱动,但当前实现主要还是基于轮询。未来的Kubernetes版本可能引入更多的事件驱动机制以提高效率。两种方式启动在 Kubernetes(通常简称为 K8s)中,有两种主要的方式来启动 Pod:使用 Deployment 和使用 Pod 直接。1.使用 Deployment 启动 Pod(部署控制器启动):Deployments 是 Kubernetes 中的一种资源类型,用于管理 Pod 的部署和更新。Deployment 提供了很多高级功能,如滚动升级、自动恢复、回滚等。步骤:创建一个 Deployment 定义文件(通常是 YAML 格式),其中包含 Pod 模板、副本数和其他配置。使用 kubectl apply -f <deployment.yaml> 命令将 Deployment 定义应用到集群。Kubernetes 控制平面会创建一个或多个 Pod 副本,以满足 Deployment 定义中指定的副本数目。如果需要更新 Pod,只需更新 Deployment 定义文件,然后使用 kubectl apply -f <updated-deployment.yaml> 进行更新。Kubernetes 会自动执行滚动升级,逐步替换旧的 Pod 副本为新的。2.使用 Pod 直接启动 Pod(标准启动):这种方式相对较少使用,因为它没有 Deployment 那样的自动化管理功能,但在某些情况下仍然有用,比如需要直接控制 Pod 的生命周期。步骤:创建一个 Pod 定义文件,其中包含容器镜像、环境变量、卷挂载等配置。使用 kubectl apply -f <pod.yaml> 命令将 Pod 定义应用到集群。Kubernetes 控制平面会直接创建一个 Pod,该 Pod 不会受到 Deployment 控制和管理,需要手动管理升级、回滚等操作。如果需要更新 Pod,必须手动修改 Pod 定义文件,然后使用 kubectl apply -f <updated-pod.yaml> 进行更新。需要注意的是,大多数情况下推荐使用 Deployment 来管理 Pod,因为它提供了更高级的管理功能,如自动扩展、滚动升级和回滚,以及更好的容错性。只有在特定需求下,或者为了特定的控制,才会考虑直接使用 Pod。镜像的升级和回滚要查看 Deployment 创建的 ReplicaSet(rs),运行 kubectl get rs。 输出类似于:NAME DESIRED CURRENT READY AGE nginx-deployment-75675f5897 3 3 3 18s更新 Deployment:1.先来更新 nginx Pod 以使用 nginx:1.16.1 镜像,而不是 nginx:1.14.2 镜像。kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.16.1或者使用下面的命令:kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1在这里,deployment/nginx-deployment 表明 Deployment 的名称,nginx 表明需要进行更新的容器, 而 nginx:1.16.1 则表示镜像的新版本以及它的标签。输出类似于:deployment.apps/nginx-deployment image updated或者,可以对 Deployment 执行 edit 操作并将 .spec.template.spec.containers[0].image 从 nginx:1.14.2 更改至 nginx:1.16.1。kubectl edit deployment/nginx-deployment输出类似于:deployment.apps/nginx-deployment edited2.要查看上线状态,运行:kubectl rollout status deployment/nginx-deployment输出类似于:Waiting for rollout to finish: 2 out of 3 new replicas have been updated...或者deployment "nginx-deployment" successfully rolled out获取关于已更新的 Deployment 的更多信息:在上线成功后,可以通过运行 kubectl get deployments 来查看 Deployment: 输出类似于:NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 3/3 3 3 36s运行 kubectl get rs 以查看 Deployment 通过创建新的 ReplicaSet 并将其扩容到 3 个副本并将旧 ReplicaSet 缩容到 0 个副本完成了 Pod 的更新操作:kubectl get rs输出类似于:NAME DESIRED CURRENT READY AGE nginx-deployment-1564180365 3 3 3 6s nginx-deployment-2035384211 0 0 0 36s现在运行 get pods 应仅显示新的 Pod:kubectl get pods输出类似于:NAME READY STATUS RESTARTS AGE nginx-deployment-1564180365-khku8 1/1 Running 0 14s nginx-deployment-1564180365-nacti 1/1 Running 0 14s nginx-deployment-1564180365-z9gth 1/1 Running 0 14s 获取 Deployment 的更多信息kubectl describe deployments回滚说明:Deployment 被触发上线时,系统就会创建 Deployment 的新的修订版本。 这意味着仅当 Deployment 的 Pod 模板(.spec.template)发生更改时,才会创建新修订版本 – 例如,模板的标签或容器镜像发生变化。 其他更新,如 Deployment 的扩缩容操作不会创建 Deployment 修订版本。 这是为了方便同时执行手动缩放或自动缩放。 换言之,当你回滚到较早的修订版本时,只有 Deployment 的 Pod 模板部分会被回滚。假设你在更新 Deployment 时犯了一个拼写错误,将镜像名称命名设置为 nginx:1.161 而不是 nginx:1.16.1:kubectl set image deployment/nginx-deployment nginx=nginx:1.161输出类似于:deployment.apps/nginx-deployment image updated此上线进程会出现停滞。你可以通过检查上线状态来验证:kubectl rollout status deployment/nginx-deployment输出类似于:Waiting for rollout to finish: 1 out of 3 new replicas have been updated...按 Ctrl-C 停止上述上线状态观测。有关上线停滞的详细信息,参考这里。你可以看到旧的副本有两个(nginx-deployment-1564180365 和 nginx-deployment-2035384211), 新的副本有 1 个(nginx-deployment-3066724191):kubectl get rs输出类似于:NAME DESIRED CURRENT READY AGE nginx-deployment-1564180365 3 3 3 25s nginx-deployment-2035384211 0 0 0 36s nginx-deployment-3066724191 1 1 0 6s查看所创建的 Pod,你会注意到新 ReplicaSet 所创建的 1 个 Pod 卡顿在镜像拉取循环中。kubectl get pods输出类似于:NAME READY STATUS RESTARTS AGE nginx-deployment-1564180365-70iae 1/1 Running 0 25s nginx-deployment-1564180365-jbqqo 1/1 Running 0 25s nginx-deployment-1564180365-hysrc 1/1 Running 0 25s nginx-deployment-3066724191-08mng 0/1 ImagePullBackOff 0 6s说明:Deployment 控制器自动停止有问题的上线过程,并停止对新的 ReplicaSet 扩容。 这行为取决于所指定的 rollingUpdate 参数(具体为 maxUnavailable)。 默认情况下,Kubernetes 将此值设置为 25%。获取 Deployment 描述信息:kubectl describe deployment输出类似于:Name: nginx-deployment Namespace: default CreationTimestamp: Tue, 15 Mar 2016 14:48:04 -0700 Labels: app=nginx Selector: app=nginx Replicas: 3 desired | 1 updated | 4 total | 3 available | 1 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 25% max unavailable, 25% max surge Pod Template: Labels: app=nginx Containers: nginx: Image: nginx:1.161 Port: 80/TCP Host Port: 0/TCP Environment: <none> Mounts: <none> Volumes: <none> Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True ReplicaSetUpdated OldReplicaSets: nginx-deployment-1564180365 (3/3 replicas created) NewReplicaSet: nginx-deployment-3066724191 (1/1 replicas created) Events: FirstSeen LastSeen Count From SubObjectPath Type Reason Message --------- -------- ----- ---- ------------- -------- ------ ------- 1m 1m 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-2035384211 to 3 22s 22s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 1 22s 22s 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 2 22s 22s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 2 21s 21s 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 1 21s 21s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 3 13s 13s 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 0 13s 13s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-3066724191 to 1要解决此问题,需要回滚到以前稳定的 Deployment 版本。检查 Deployment 历史版本按照如下步骤检查回滚历史:1.首先,检查 Deployment 修订历史:kubectl rollout history deployment/nginx-deployment输出类似于:deployments "nginx-deployment" REVISION CHANGE-CAUSE 1 kubectl apply --filename=https://k8s.io/examples/controllers/nginx-deployment.yaml 2 kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1 3 kubectl set image deployment/nginx-deployment nginx=nginx:1.161CHANGE-CAUSE 的内容是从 Deployment 的 kubernetes.io/change-cause 注解复制过来的。 复制动作发生在修订版本创建时。你可以通过以下方式设置 CHANGE-CAUSE 消息:使用 kubectl annotate deployment/nginx-deployment kubernetes.io/change-cause="image updated to 1.16.1" 为 Deployment 添加注解。手动编辑资源的清单。2.要查看修订历史的详细信息,运行:kubectl rollout history deployment/nginx-deployment --revision=2输出类似于:deployments "nginx-deployment" revision 2 Labels: app=nginx pod-template-hash=1159050644 Annotations: kubernetes.io/change-cause=kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1 Containers: nginx: Image: nginx:1.16.1 Port: 80/TCP QoS Tier: cpu: BestEffort memory: BestEffort Environment Variables: <none> No volumes.回滚到之前的修订版本按照下面给出的步骤将 Deployment 从当前版本回滚到以前的版本(即版本 2)。1.假定现在你已决定撤消当前上线并回滚到以前的修订版本:kubectl rollout undo deployment/nginx-deployment输出类似于:deployment.apps/nginx-deployment rolled back或者,你也可以通过使用 --to-revision 来回滚到特定修订版本:kubectl rollout undo deployment/nginx-deployment --to-revision=2输出类似于:deployment.apps/nginx-deployment rolled back与回滚相关的指令的更详细信息,请参考 kubectl rollout。现在,Deployment 正在回滚到以前的稳定版本。正如你所看到的,Deployment 控制器生成了回滚到修订版本 2 的 DeploymentRollback 事件。2.检查回滚是否成功以及 Deployment 是否正在运行,运行:kubectl get deployment nginx-deployment输出类似于:NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 3/3 3 3 30m3.获取 Deployment 描述信息:kubectl describe deployment nginx-deployment输出类似于:Name: nginx-deployment Namespace: default CreationTimestamp: Sun, 02 Sep 2018 18:17:55 -0500 Labels: app=nginx Annotations: deployment.kubernetes.io/revision=4 kubernetes.io/change-cause=kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1 Selector: app=nginx Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 25% max unavailable, 25% max surge Pod Template: Labels: app=nginx Containers: nginx: Image: nginx:1.16.1 Port: 80/TCP Host Port: 0/TCP Environment: <none> Mounts: <none> Volumes: <none> Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True NewReplicaSetAvailable OldReplicaSets: <none> NewReplicaSet: nginx-deployment-c4747d96c (3/3 replicas created) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScalingReplicaSet 12m deployment-controller Scaled up replica set nginx-deployment-75675f5897 to 3 Normal ScalingReplicaSet 11m deployment-controller Scaled up replica set nginx-deployment-c4747d96c to 1 Normal ScalingReplicaSet 11m deployment-controller Scaled down replica set nginx-deployment-75675f5897 to 2 Normal ScalingReplicaSet 11m deployment-controller Scaled up replica set nginx-deployment-c4747d96c to 2 Normal ScalingReplicaSet 11m deployment-controller Scaled down replica set nginx-deployment-75675f5897 to 1 Normal ScalingReplicaSet 11m deployment-controller Scaled up replica set nginx-deployment-c4747d96c to 3 Normal ScalingReplicaSet 11m deployment-controller Scaled down replica set nginx-deployment-75675f5897 to 0 Normal ScalingReplicaSet 11m deployment-controller Scaled up replica set nginx-deployment-595696685f to 1 Normal DeploymentRollback 15s deployment-controller Rolled back deployment "nginx-deployment" to revision 2 Normal ScalingReplicaSet 15s deployment-controller Scaled down replica set nginx-deployment-595696685f to 03.缩放 Deployment你可以使用如下指令缩放 Deployment:kubectl scale deployment/nginx-deployment --replicas=10输出类似于:deployment.apps/nginx-deployment scaled假设集群启用了Pod 的水平自动缩放, 你可以为 Deployment 设置自动缩放器,并基于现有 Pod 的 CPU 利用率选择要运行的 Pod 个数下限和上限。kubectl autoscale deployment/nginx-deployment --min=10 --max=15 --cpu-percent=80输出类似于:deployment.apps/nginx-deployment scaled比例缩放RollingUpdate 的 Deployment 支持同时运行应用程序的多个版本。 当自动缩放器缩放处于上线进程(仍在进行中或暂停)中的 RollingUpdate Deployment 时, Deployment 控制器会平衡现有的活跃状态的 ReplicaSets(含 Pod 的 ReplicaSets)中的额外副本, 以降低风险。这称为 比例缩放(Proportional Scaling)。例如,你正在运行一个 10 个副本的 Deployment,其 maxSurge=3,maxUnavailable=2。确保 Deployment 的这 10 个副本都在运行。kubectl get deploy输出类似于:NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx-deployment 10 10 10 10 50s更新 Deployment 使用新镜像,碰巧该镜像无法从集群内部解析。kubectl set image deployment/nginx-deployment nginx=nginx:sometag输出类似于:deployment.apps/nginx-deployment image updated镜像更新使用 ReplicaSet nginx-deployment-1989198191 启动新的上线过程, 但由于上面提到的 maxUnavailable 要求,该进程被阻塞了。检查上线状态:kubectl get rs输出类似于:NAME DESIRED CURRENT READY AGE nginx-deployment-1989198191 5 5 0 9s nginx-deployment-618515232 8 8 8 1m然后,出现了新的 Deployment 扩缩请求。自动缩放器将 Deployment 副本增加到 15。 Deployment 控制器需要决定在何处添加 5 个新副本。如果未使用比例缩放,所有 5 个副本 都将添加到新的 ReplicaSet 中。使用比例缩放时,可以将额外的副本分布到所有 ReplicaSet。 较大比例的副本会被添加到拥有最多副本的 ReplicaSet,而较低比例的副本会进入到 副本较少的 ReplicaSet。所有剩下的副本都会添加到副本最多的 ReplicaSet。 具有零副本的 ReplicaSets 不会被扩容。在上面的示例中,3 个副本被添加到旧 ReplicaSet 中,2 个副本被添加到新 ReplicaSet。 假定新的副本都很健康,上线过程最终应将所有副本迁移到新的 ReplicaSet 中。 要确认这一点,请运行:kubectl get deploy输出类似于:NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx-deployment 15 18 7 8 7m上线状态确认了副本是如何被添加到每个 ReplicaSet 的。kubectl get rs输出类似于:NAME DESIRED CURRENT READY AGE nginx-deployment-1989198191 7 7 0 7m nginx-deployment-618515232 11 11 11 7m暂停、恢复 Deployment 的上线过程在你更新一个 Deployment 的时候,或者计划更新它的时候, 你可以在触发一个或多个更新之前暂停 Deployment 的上线过程。 当你准备应用这些变更时,你可以重新恢复 Deployment 上线过程。 这样做使得你能够在暂停和恢复执行之间应用多个修补程序,而不会触发不必要的上线操作。例如,对于一个刚刚创建的 Deployment:获取该 Deployment 信息:kubectl get deploy输出类似于:NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx 3 3 3 3 1m获取上线状态:kubectl get rs输出类似于:NAME DESIRED CURRENT READY AGE nginx-2142116321 3 3 3 1m使用如下指令暂停上线:kubectl rollout pause deployment/nginx-deployment输出类似于:deployment.apps/nginx-deployment paused接下来更新 Deployment 镜像:kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1输出类似于:deployment.apps/nginx-deployment image updated注意没有新的上线被触发:kubectl rollout history deployment/nginx-deployment输出类似于:deployments "nginx" REVISION CHANGE-CAUSE 1 <none>获取上线状态验证现有的 ReplicaSet 没有被更改:kubectl get rs输出类似于:NAME DESIRED CURRENT READY AGE nginx-2142116321 3 3 3 2m你可以根据需要执行很多更新操作,例如,可以要使用的资源:kubectl set resources deployment/nginx-deployment -c=nginx --limits=cpu=200m,memory=512Mi输出类似于:deployment.apps/nginx-deployment resource requirements updated暂停 Deployment 上线之前的初始状态将继续发挥作用,但新的更新在 Deployment 上线被暂停期间不会产生任何效果。最终,恢复 Deployment 上线并观察新的 ReplicaSet 的创建过程,其中包含了所应用的所有更新:kubectl rollout resume deployment/nginx-deployment输出类似于这样:deployment.apps/nginx-deployment resumed观察上线的状态,直到完成。kubectl get rs -w输出类似于:NAME DESIRED CURRENT READY AGE nginx-2142116321 2 2 2 2m nginx-3926361531 2 2 0 6s nginx-3926361531 2 2 1 18s nginx-2142116321 1 2 2 2m nginx-2142116321 1 2 2 2m nginx-3926361531 3 2 1 18s nginx-3926361531 3 2 1 18s nginx-2142116321 1 1 1 2m nginx-3926361531 3 3 1 18s nginx-3926361531 3 3 2 19s nginx-2142116321 0 1 1 2m nginx-2142116321 0 1 1 2m nginx-2142116321 0 0 0 2m nginx-3926361531 3 3 3 20s获取最近上线的状态:kubectl get rs输出类似于:NAME DESIRED CURRENT READY AGE nginx-2142116321 0 0 0 2m nginx-3926361531 3 3 3 28s说明:你不可以回滚处于暂停状态的 Deployment,除非先恢复其执行状态。Deployment 状态Deployment 的生命周期中会有许多状态。上线新的 ReplicaSet 期间可能处于 Progressing(进行中),可能是 Complete(已完成),也可能是 Failed(失败)以至于无法继续进行。进行中的 Deployment执行下面的任务期间,Kubernetes 标记 Deployment 为进行中(Progressing)_:Deployment 创建新的 ReplicaSetDeployment 正在为其最新的 ReplicaSet 扩容Deployment 正在为其旧有的 ReplicaSet(s) 缩容新的 Pod 已经就绪或者可用(就绪至少持续了 MinReadySeconds 秒)。当上线过程进入“Progressing”状态时,Deployment 控制器会向 Deployment 的 .status.conditions 中添加包含下面属性的状况条目:type: Progressingstatus: "True"reason: NewReplicaSetCreated | reason: FoundNewReplicaSet | reason: ReplicaSetUpdated你可以使用 kubectl rollout status 监视 Deployment 的进度。完成的 Deployment当 Deployment 具有以下特征时,Kubernetes 将其标记为完成(Complete);与 Deployment 关联的所有副本都已更新到指定的最新版本,这意味着之前请求的所有更新都已完成。与 Deployment 关联的所有副本都可用。未运行 Deployment 的旧副本。当上线过程进入“Complete”状态时,Deployment 控制器会向 Deployment 的 .status.conditions 中添加包含下面属性的状况条目:type: Progressingstatus: "True"reason: NewReplicaSetAvailable这一 Progressing 状况的状态值会持续为 "True",直至新的上线动作被触发。 即使副本的可用状态发生变化(进而影响 Available 状况),Progressing 状况的值也不会变化。你可以使用 kubectl rollout status 检查 Deployment 是否已完成。 如果上线成功完成,kubectl rollout status 返回退出代码 0。kubectl rollout status deployment/nginx-deployment输出类似于:Waiting for rollout to finish: 2 of 3 updated replicas are available... deployment "nginx-deployment" successfully rolled out从 kubectl rollout 命令获得的返回状态为 0(成功):echo $? 0失败的 Deployment你的 Deployment 可能会在尝试部署其最新的 ReplicaSet 受挫,一直处于未完成状态。 造成此情况一些可能因素如下:配额(Quota)不足就绪探测(Readiness Probe)失败镜像拉取错误权限不足限制范围(Limit Ranges)问题应用程序运行时的配置错误检测此状况的一种方法是在 Deployment 规约中指定截止时间参数: (.spec.progressDeadlineSeconds)。 .spec.progressDeadlineSeconds 给出的是一个秒数值,Deployment 控制器在(通过 Deployment 状态) 标示 Deployment 进展停滞之前,需要等待所给的时长。以下 kubectl 命令设置规约中的 progressDeadlineSeconds,从而告知控制器 在 10 分钟后报告 Deployment 的上线没有进展:kubectl patch deployment/nginx-deployment -p '{"spec":{"progressDeadlineSeconds":600}}'输出类似于:deployment.apps/nginx-deployment patched超过截止时间后,Deployment 控制器将添加具有以下属性的 Deployment 状况到 Deployment 的 .status.conditions 中:type: Progressingstatus: "False"reason: ProgressDeadlineExceeded这一状况也可能会比较早地失败,因而其状态值被设置为 "False", 其原因为 ReplicaSetCreateError。 一旦 Deployment 上线完成,就不再考虑其期限。参考 Kubernetes API Conventions 获取更多状态状况相关的信息。说明:除了报告 Reason=ProgressDeadlineExceeded 状态之外,Kubernetes 对已停止的 Deployment 不执行任何操作。更高级别的编排器可以利用这一设计并相应地采取行动。 例如,将 Deployment 回滚到其以前的版本。说明:如果你暂停了某个 Deployment 上线,Kubernetes 不再根据指定的截止时间检查 Deployment 上线的进展。 你可以在上线过程中间安全地暂停 Deployment 再恢复其执行,这样做不会导致超出最后时限的问题。Deployment 可能会出现瞬时性的错误,可能因为设置的超时时间过短, 也可能因为其他可认为是临时性的问题。例如,假定所遇到的问题是配额不足。 如果描述 Deployment,你将会注意到以下部分:kubectl describe deployment nginx-deployment输出类似于:<...> Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True ReplicaSetUpdated ReplicaFailure True FailedCreate <...>如果运行 kubectl get deployment nginx-deployment -o yaml,Deployment 状态输出 将类似于这样:status: availableReplicas: 2 conditions: - lastTransitionTime: 2016-10-04T12:25:39Z lastUpdateTime: 2016-10-04T12:25:39Z message: Replica set "nginx-deployment-4262182780" is progressing. reason: ReplicaSetUpdated status: "True" type: Progressing - lastTransitionTime: 2016-10-04T12:25:42Z lastUpdateTime: 2016-10-04T12:25:42Z message: Deployment has minimum availability. reason: MinimumReplicasAvailable status: "True" type: Available - lastTransitionTime: 2016-10-04T12:25:39Z lastUpdateTime: 2016-10-04T12:25:39Z message: 'Error creating: pods "nginx-deployment-4262182780-" is forbidden: exceeded quota: object-counts, requested: pods=1, used: pods=3, limited: pods=2' reason: FailedCreate status: "True" type: ReplicaFailure observedGeneration: 3 replicas: 2 unavailableReplicas: 2 最终,一旦超过 Deployment 进度限期,Kubernetes 将更新状态和进度状况的原因:Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing False ProgressDeadlineExceeded ReplicaFailure True FailedCreate可以通过缩容 Deployment 或者缩容其他运行状态的控制器,或者直接在命名空间中增加配额 来解决配额不足的问题。如果配额条件满足,Deployment 控制器完成了 Deployment 上线操作, Deployment 状态会更新为成功状况(Status=True 和 Reason=NewReplicaSetAvailable)。Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True NewReplicaSetAvailabletype: Available 加上 status: True 意味着 Deployment 具有最低可用性。 最低可用性由 Deployment 策略中的参数指定。 type: Progressing 加上 status: True 表示 Deployment 处于上线过程中,并且正在运行, 或者已成功完成进度,最小所需新副本处于可用。 请参阅对应状况的 Reason 了解相关细节。 在我们的案例中 reason: NewReplicaSetAvailable 表示 Deployment 已完成。你可以使用 kubectl rollout status 检查 Deployment 是否未能取得进展。 如果 Deployment 已超过进度限期,kubectl rollout status 返回非零退出代码。kubectl rollout status deployment/nginx-deployment输出类似于:Waiting for rollout to finish: 2 out of 3 new replicas have been updated... error: deployment "nginx" exceeded its progress deadlinekubectl rollout 命令的退出状态为 1(表明发生了错误):echo $? 1对失败 Deployment 的操作可应用于已完成的 Deployment 的所有操作也适用于失败的 Deployment。 你可以对其执行扩缩容、回滚到以前的修订版本等操作,或者在需要对 Deployment 的 Pod 模板应用多项调整时,将 Deployment 暂停。清理策略你可以在 Deployment 中设置 .spec.revisionHistoryLimit 字段以指定保留此 Deployment 的多少个旧有 ReplicaSet。其余的 ReplicaSet 将在后台被垃圾回收。 默认情况下,此值为 10。说明:显式将此字段设置为 0 将导致 Deployment 的所有历史记录被清空,因此 Deployment 将无法回滚。金丝雀部署如果要使用 Deployment 向用户子集或服务器子集上线版本, 则可以遵循资源管理所描述的金丝雀模式, 创建多个 Deployment,每个版本一个。编写 Deployment 规约同其他 Kubernetes 配置一样, Deployment 需要 .apiVersion,.kind 和 .metadata 字段。 有关配置文件的其他信息,请参考部署 Deployment、 配置容器和使用 kubectl 管理资源等相关文档。当控制面为 Deployment 创建新的 Pod 时,Deployment 的 .metadata.name 是命名这些 Pod 的部分基础。 Deployment 的名称必须是一个合法的 DNS 子域值, 但这会对 Pod 的主机名产生意外的结果。为获得最佳兼容性,名称应遵循更严格的 DNS 标签规则。Deployment 还需要 .spec` 部分设置资源限制$ kubectl set resources deployment nginx -c=nginx --limits=cpu=200m,memory=512Mi deployment "nginx" resource requirements updatedHAP需要提前安装HorizontalPodAutoscaler(简称 HPA ) 自动更新工作负载资源(例如 Deployment 或者 StatefulSet), 目的是自动扩缩工作负载以满足需求。水平扩缩意味着对增加的负载的响应是部署更多的 Pod。 这与“垂直(Vertical)”扩缩不同,对于 Kubernetes, 垂直扩缩意味着将更多资源(例如:内存或 CPU)分配给已经为工作负载运行的 Pod。[root@k8smaster hpa]# kubectl get pod -o wide [root@k8smaster hpa]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 20d创建 HorizontalPodAutoscaler:kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10你可以通过运行以下命令检查新制作的 HorizontalPodAutoscaler 的当前状态:kubectl get hpa输出类似于:NAME REFERENCE TARGET MINPODS MAXPODS REPLICAS AGE php-apache Deployment/php-apache/scale 0% / 50% 1 10 1 18s增加负载接下来,看看自动扩缩器如何对增加的负载做出反应。 为此,你将启动一个不同的 Pod 作为客户端。 客户端 Pod 中的容器在无限循环中运行,向 php-apache 服务发送查询。# 在单独的终端中运行它 # 以便负载生成继续,你可以继续执行其余步骤 kubectl run -i --tty load-generator --rm --image=busybox:1.28 --restart=Never -- /bin/sh -c "while sleep 0.01; do wget -q -O- http://php-apache; done"现在执行:# 准备好后按 Ctrl+C 结束观察 kubectl get hpa php-apache --watch一分钟时间左右之后,通过以下命令,我们可以看到 CPU 负载升高了;例如:NAME REFERENCE TARGET MINPODS MAXPODS REPLICAS AGE php-apache Deployment/php-apache/scale 305% / 50% 1 10 1 3m然后,更多的副本被创建。例如:NAME REFERENCE TARGET MINPODS MAXPODS REPLICAS AGE php-apache Deployment/php-apache/scale 305% / 50% 1 10 7 3m这时,由于请求增多,CPU 利用率已经升至请求值的 305%。 可以看到,Deployment 的副本数量已经增长到了 7:kubectl get deployment php-apache你应该会看到与 HorizontalPodAutoscaler 中的数字与副本数匹配NAME READY UP-TO-DATE AVAILABLE AGE php-apache 7/7 7 7 19m说明: 有时最终副本的数量可能需要几分钟才能稳定下来。由于环境的差异, 不同环境中最终的副本数量可能与本示例中的数量不同。停止产生负载要完成该示例,请停止发送负载。在我们创建 busybox 容器的终端中,输入 <Ctrl> + C 来终止负载的产生。然后验证结果状态(大约一分钟后):# 准备好后按 Ctrl+C 结束观察 kubectl get hpa php-apache --watch输出类似于:NAME REFERENCE TARGET MINPODS MAXPODS REPLICAS AGE php-apache Deployment/php-apache/scale 0% / 50% 1 10 1 11mDeployment 也显示它已经缩小了:kubectl get deployment php-apache NAME READY UP-TO-DATE AVAILABLE AGE php-apache 1/1 1 1 27m一旦 CPU 利用率降至 0,HPA 会自动将副本数缩减为 1。自动扩缩完成副本数量的改变可能需要几分钟的时间。init容器在 Kubernetes(K8s)中,Init 容器(Init Containers)是一种特殊类型的容器,它负责在主容器运行之前执行一些初始化任务。Init 容器与主容器是串行运行的,即 Init 容器中的任务完成后,主容器才会启动。以下是有关 Kubernetes 中 Init 容器的详细解释:1. 用途和优势:初始化任务: Init 容器用于执行初始化任务,例如加载配置、预热缓存、初始化数据库等。这些任务通常是主容器运行之前必须完成的操作。解耦初始化逻辑: 使用 Init 容器可以将初始化逻辑从主容器中解耦,使主容器只关注应用程序的业务逻辑,提高了可维护性和可重用性。2. 特点和工作方式:串行运行: Init 容器和主容器是串行运行的,即 Init 容器中的任务完成后,主容器才会启动。共享存储和网络: Init 容器与主容器共享相同的存储卷(Volume)和网络命名空间,因此它们可以在相同的环境中运行。3. 使用示例:以下是一个简单的 Pod YAML 文件,其中包含了一个 Init 容器和一个主容器:apiVersion: v1 kind: Pod metadata: name: mypod spec: containers: - name: main-container image: nginx:latest initContainers: - name: init-container image: busybox:latest command: ['sh', '-c', 'echo "Initialization complete; starting main container"']在这个示例中,init-container 是一个使用 BusyBox 镜像的 Init 容器,它执行了一个简单的 echo 命令。一旦 init-container 完成任务,主容器 main-container 就会启动。4. 生命周期和状态:Init 容器的生命周期: Init 容器的生命周期与主容器类似,包括创建、启动、停止和删除。状态传递: Init 容器的状态对主容器是不可见的,但如果 Init 容器失败(非零退出码),主容器不会启动。5. 多个 Init 容器:多个初始化容器: 一个 Pod 可以包含多个 Init 容器,它们按照声明的顺序依次执行。依赖关系: 可以通过 init 容器的执行结果作为后续 init 容器的输入,实现一些复杂的初始化逻辑。6. 注意事项:超时和重试: 可以配置 Init 容器的超时时间,如果在规定时间内未完成,Pod 将被认为启动失败。并发初始化: Init 容器是串行执行的,如果需要并发执行,可以考虑使用多个 Init 容器。总体而言,Init 容器是 Kubernetes 中一项强大的功能,它允许开发者在容器启动之前执行一些必要的初始化任务,提高了容器化应用的灵活性和可维护性。pause容器在 Kubernetes 中,Pause 容器是每个 Pod 中的一个特殊容器,它的主要目的是保持 Pod 的网络命名空间(Network Namespace)以及其他共享的命名空间(例如 PID 命名空间)的存在。Pause 容器是 Kubernetes 实现多容器 Pod 的一部分,它在 Pod 启动时运行,而且在 Pod 中的其他容器启动之前一直运行。以下是 Pause 容器的一些详细解释:1. 作用和目的:保持命名空间: Pause 容器的主要目的是保持 Pod 的网络命名空间,确保其他容器能够在相同的网络环境中运行。这有助于实现容器之间的网络隔离。协调容器启动: Pause 容器还用于协调其他容器的启动顺序,确保它们按照正确的顺序启动。启用 pid 命名空间,2. 镜像和进程:基础镜像: Pause 容器通常使用一个极小的基础镜像,其中包含最小化的文件系统和可执行文件。在 Docker 中,通常使用 busybox 或 alpine 作为 Pause 容器的基础镜像。无限循环: Pause 容器启动后通常执行一个无限循环的命令,以保持容器处于运行状态。3. 生命周期和状态:持续运行: Pause 容器一直运行,直到 Pod 被终止。无法被用户访问: Pause 容器通常不对用户提供服务,也不对用户可见。用户主要与 Pod 中的其他业务容器交互。4. 网络隔离:共享网络: Pause 容器与其他容器共享相同的网络命名空间,这意味着它们可以通过 localhost 进行通信。Pod 中的其他容器: Pod 中的其他容器可以通过网络共享与 Pause 容器通信,从而实现容器之间的网络隔离。5. 进程隔离:PID 命名空间: Pause 容器通常也会与其他容器共享相同的 PID 命名空间,以便它们能够看到同一组进程。6. 使用示例:Pod YAML 示例:apiVersion: v1 kind: Pod metadata: name: mypod spec: containers: - name: main-container image: nginx:latest在这个示例中,mypodPod 包含一个main-container和一个 Pause 容器。Pause 容器将保持网络和 PID 命名空间的存在。7. 其他示例我们首先在节点上运行一个 pause 容器。docker run -d --name pause -p 8880:80 --ipc=shareable jimmysong/pause-amd64:3.0这个 Docker 命令是在后台运行一个名为 “pause” 的容器,使用了 “jimmysong/pause-amd64:3.0” 镜像。以下是各个选项的解释:docker run: 运行容器的命令。-d: 在后台运行容器,即以守护进程方式运行。--name pause: 为容器指定一个名字,这里是 “pause”。-p 8880:80: 将容器的端口映射到主机的端口,将容器内部的端口 80 映射到主机的端口 8880。--ipc=shareable: 允许与其他容器共享 IPC(Inter-Process Communication)命名空间。IPC 共享是容器间进程通信的一种方式。镜像:jimmysong/pause-amd64:3.0: 使用名为 “pause-amd64” 的镜像,该镜像的版本是 “3.0”。这个镜像通常被用作 Kubernetes 等容器编排系统中的 Pause 容器。Pause 容器的作用是维持 Pod 中的网络命名空间,确保其他容器能够在相同的网络环境中运行,并且也被用于协调容器启动顺序。通过这个命令,你创建了一个后台运行的容器,它使用指定的镜像,并映射容器端口到主机端口。这个容器是一个示例,通常在实际应用中,“pause” 容器是由容器编排系统(如 Kubernetes)自动创建和管理的。然后再运行一个 nginx 容器,nginx 将为 localhost:2368 创建一个代理。#编辑nginx.conf文件 $ cat <<EOF >> nginx.conf error_log stderr; events { worker_connections 1024; } http { access_log /dev/stdout combined; server { listen 80 default_server; server_name example.com www.example.com; location / { proxy_pass http://127.0.0.1:2368; } } } EOF # 运行 $ docker run -d --name nginx -v `pwd`/nginx.conf:/etc/nginx/nginx.conf --net=container:pause --ipc=container:pause --pid=container:pause nginx这个命令涉及创建一个名为 “nginx” 的 Docker 容器,运行 Nginx 服务,并将 Nginx 的配置文件从主机挂载到容器内。以下是命令的详解:1.cat <<EOF >> nginx.conf:    这是一个 shell 的 Here 文档,用于将多行文本追加到 nginx.conf 文件。    EOF 是 Here 文档的结束标记。2.配置文件内容:    在 Here 文档中,你提供了 Nginx 的配置文件内容,其中包括:        将错误日志输出到标准错误流(error_log stderr;)。        配置 Nginx 事件(events)和 HTTP 部分,指定 worker 连接数、访问日志位置等。        配置一个简单的 Nginx 服务器,监听在80端口,将请求代理到 http://127.0.0.1:2368。3.docker run -d --name nginx ...:   docker run: 运行容器的命令。    -d: 后台运行容器,即以守护进程方式运行。   --name nginx: 为容器指定一个名字,这里是 “nginx”。    -vpwd/nginx.conf:/etc/nginx/nginx.conf: 将主机上的 nginx.conf 文件挂载到容器内的 /etc/nginx/nginx.conf,这样 Nginx 将使用这个配置文件。   --net=container:pause: 共享网络命名空间,使得 Nginx 和 “pause” 容器共享相同的网络环境。这通常用于确保容器在相同的网络环境中运行。    --ipc=container:pause: 共享 IPC 命名空间,容器间可以通过 IPC 进行通信。    --pid=container:pause: 共享 PID 命名空间,容器间可以看到相同的进程 ID。    nginx: 使用的 Docker 镜像,即运行 Nginx 服务。通过这个命令,你创建了一个后台运行的 Nginx 容器,并在运行时将 Nginx 的配置文件加载进来。这样,你可以在主机上编辑 nginx.conf,并且不需要重新启动容器即可应用新的配置。容器共享网络、IPC、PID 命名空间,这通常在某些场景下是有用的,比如容器编排系统中的多容器协同工作。然后再为 ghost 创建一个应用容器,这是一款博客软件。$ docker run -d --name ghost --net=container:pause --ipc=container:pause --pid=container:pause ghostdocker run: Docker 命令,用于运行容器。-d: 后台运行容器,即以守护进程方式运行。--name ghost: 为容器指定一个名字,这里是 “ghost”。--net=container:pause: 共享网络命名空间,即与指定的 “pause” 容器共享相同的网络环境。这通常用于确保容器在相同的网络环境中运行。--ipc=container:pause: 共享 IPC 命名空间,与指定的 “pause” 容器共享相同的 IPC 资源。这使得容器之间可以进行进程间通信。--pid=container:pause: 共享 PID 命名空间,与指定的 “pause” 容器共享相同的进程 ID。这使得容器之间能够看到相同的进程视图。ghost: 使用的 Docker 镜像,这里是 “ghost”。Ghost 是一个开源的博客平台。现在访问 http://localhost:8880/ 就可以看到 ghost 博客的界面了。解析pause 容器将内部的 80 端口映射到宿主机的 8880 端口,pause 容器在宿主机上设置好了网络 namespace 后,nginx 容器加入到该网络 namespace 中,我们看到 nginx 容器启动的时候指定了 --net=container:pause,ghost 容器同样加入到了该网络 namespace 中,这样三个容器就共享了网络,互相之间就可以使用 localhost 直接通信,--ipc=container:pause --pid=container:pause 就是三个容器处于同一个 namespace 中,init 进程为 pause,这时我们进入到 ghost 容器中查看进程情况。# ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.0 1024 4 ? Ss 13:49 0:00 /pause root 5 0.0 0.1 32432 5736 ? Ss 13:51 0:00 nginx: master p systemd+ 9 0.0 0.0 32980 3304 ? S 13:51 0:00 nginx: worker p node 10 0.3 2.0 1254200 83788 ? Ssl 13:53 0:03 node current/in root 79 0.1 0.0 4336 812 pts/0 Ss 14:09 0:00 sh root 87 0.0 0.0 17500 2080 pts/0 R+ 14:10 0:00 ps aux在 ghost 容器中同时可以看到 pause 和 nginx 容器的进程,并且 pause 容器的 PID 是 1。而在 Kubernetes 中容器的 PID=1 的进程即为容器本身的业务进程。8. 其他容器启动依赖:协调容器启动: Pause 容器的存在确保其他容器在正确的顺序启动。这对于依赖于共享网络命名空间的容器启动顺序非常重要。总体而言,Pause 容器在 Kubernetes 中扮演着维持网络隔离和协调其他容器启动的重要角色。虽然用户通常不与 Pause 容器直接交互,但它在底层确保了多容器 Pod 的正常运行。pod安全策略Pod 安全策略(Pod Security Policy) 是集群级别的资源,它能够控制Pod规约 中与安全性相关的各个方面。PodSecurityPolicy 对象定义了一组Pod运行时必须遵循的条件及相关字段的默认值,只有 Pod 满足这些条件才会被系统接受。下列PodSecurityPolicy表示是不允许创建特权模式的PodapiVersion: policy/v1beta1 kind: PodSecurityPolicy metadata: name: permissive spec: privileged: false allowPrivilegeEscalation: true readOnlyRootFilesystem: false seLinux: rule: RunAsAny supplementalGroups: rule: RunAsAny runAsUser: rule: RunAsAny fsGroup: rule: RunAsAny allowedCapabilities: - '*' hostPorts: - min: 8000 max: 8080 volumes: - '*'创建之后查看:kubectl get psp 或者 kubectl get podSecurityPolicy上面的PodSecurytiPolicy是设置了不允许创建特权模式的Pod,例如,在下面的YAML配置文件pod-privileged.yaml中为Pod设置了特权模式:获取 Pod 安全策略列表获取已存在策略列表,使用 kubectl get:[root@k8smaster security]# kubectl get psp NAME PRIV CAPS SELINUX RUNASUSER FSGROUP SUPGROUP READONLYROOTFS VOLUMES permissive false * RunAsAny RunAsAny RunAsAny RunAsAny false *修改 Pod 安全策略通过交互方式修改策略,使用 kubectl edit:kubectl edit psp permissive该命令将打开一个默认文本编辑器,在这里能够修改策略。删除 Pod 安全策略一旦不再需要一个策略,很容易通过 kubectl 删除它:[root@k8smaster security]# kubectl delete psp permissive podsecuritypolicy.policy "permissive" deleted [root@k8smaster security]# kubectl get psp No resources foundpod生命周期Kubernetes 中 Pod 的生命周期,包括生命周期的不同阶段、存活和就绪探针(在容器探针一篇)、重启策略等Kubernetes 中的 Pod 生命周期包括多个阶段,从 Pod 创建到终止,其中包括一系列的生命周期事件。以下是 Pod 生命周期的主要阶段(phase):1.Pending(挂起):Pod 已经被创建,但还没有被调度到一个节点上运行。这个阶段可能是由于调度问题、等待容器镜像下载等原因导致的。2.ContainerCreating(创建容器):Pod 已经被调度到节点上,但正在创建容器。这包括拉取容器镜像、创建容器等过程。3.Running(运行中):所有容器已经成功创建并且正在运行。Pod 进入这个阶段表示应用程序或服务已经在容器中运行。4.Succeeded(成功):所有容器成功运行并已经退出,Pod 处于完成状态。这通常发生在一次性任务完成后,例如 Job 类型的任务。5.Failed(失败):Pod 中的一个或多个容器已经失败。这可能是由于应用程序错误、配置问题或其他故障导致的。6.Unknown(未知):由于某种原因,Pod 的状态无法被确定。这可能是由于调度问题、通信问题等导致的。7.Terminating(终止中):Pod 正在被终止。这包括停止运行中的容器、清理资源等操作。Pod 在终止过程中可能会经历一些阶段,例如删除容器、释放网络和存储资源等。8.Terminated(已终止):Pod 已经终止,不再运行。这可能是因为正常完成、手动删除、或者发生了无法恢复的错误。Kubernetes 控制器负责监控和管理 Pod 的生命周期。例如,Deployment 控制器负责创建和维护副本集,确保指定数量的 Pod 在运行。Job 控制器则负责确保指定数量的 Pod 成功运行一次。Pod 生命周期中的事件和状态转换可以通过 kubectl describe pod <pod-name> 命令查看详细信息。这提供了对 Pod 中容器运行和终止的详细记录。pod状态Pod 有一个 PodStatus 对象,其中包含一个 PodCondition 数组。 PodCondition 数组的每个元素都有一个 type 字段和一个 status 字段。type 字段是字符串,可能的值有 PodScheduled、Ready、Initialized、Unschedulable和ContainersReady。status 字段是一个字符串,可能的值有 True、False 和 Unknown。查看pod的详细信息kubectl describe pod podname查看pod的state查看pod的type字段说明1.Initialized:    Type: Initialized 表示 Pod 是否已经完成了初始化阶段。在这个阶段,Kubernetes 正在为 Pod 设置网络和存储,确保所有容器都已启动。    Status: True 表示初始化已完成。2.Ready:    Type: Ready 表示 Pod 是否已经准备好接收网络流量。Ready 为 True 表示 Pod 已经准备好,容器已经启动并且已经可以接受请求。    Status: True 表示 Pod 已经准备好。3.ContainersReady:    Type: ContainersReady 表示 Pod 中的所有容器是否都已经准备好接收请求。Ready 仅表示主容器的准备状态,而 ContainersReady 表示所有容器都已准备好。    Status: True 表示所有容器都已准备好。4.PodScheduled:    Type: PodScheduled 表示 Pod 是否已经被成功地调度到某个节点上。调度是指 Kubernetes 决定将 Pod 放置在哪个节点上运行。    Status: True 表示 Pod 已经成功调度。pod hookKubernetes中的Pod Hook(也称为Pod生命周期钩子或Pod钩子)是一种机制,允许您在Pod的生命周期中执行自定义操作。这些操作可以包括在Pod创建前、创建后、删除前、删除后等特定时刻运行的命令或脚本。Pod Hook可用于执行与Pod相关的任务,例如初始化、清理或监控。Pod Hook主要有以下几种类型:1.PostStart:这是一个在容器启动后执行的钩子。它通常用于执行初始化任务,例如等待依赖服务启动或执行某些设置操作。如果PostStart钩子失败,Pod将被认为处于失败状态,并且Kubernetes可能会尝试重新启动该Pod。2.PreStop:这是一个在容器终止之前执行的钩子。它通常用于执行清理任务,例如保存数据或发送信号给应用程序,以便它可以正确地停止。如果PreStop钩子失败,Pod仍会终止,但Kubernetes会记录错误。3.PostStop:Kubernetes不直接支持PostStop钩子,但您可以通过容器内的进程来实现类似的功能。当容器内的进程终止时,您可以在容器中运行一些附加的操作,例如清理文件或发送通知。为了使用Pod Hook,您需要将它们定义在Pod的规范中。以下是一个Pod定义的示例,其中包含PostStart和PreStop钩子:apiVersion: v1 kind: Pod metadata: name: lifecycle-demo spec: containers: - name: lifecycle-demo-container image: nginx lifecycle: postStart: exec: command: ["/bin/sh", "-c", "echo Hello from the postStart handler> /usr/share/message"] preStop: exec: command: ["/usr/sbin/nginx","-s","quit"]这是一个Kubernetes Pod的YAML定义文件,其中定义了一个名为 lifecycle-demo 的Pod,它包含一个名为 lifecycle-demo-container 的容器,并使用了生命周期钩子来定义容器的行为。逐一解释这个YAML文件的各个部分:    apiVersion: v1:这指定了Kubernetes API版本,这里使用的是v1版本。   kind: Pod:这定义了资源类型为Pod。     metadata:这是元数据部分,用于指定Pod的元数据信息,包括名称。在这个示例中,Pod的名称为 lifecycle-demo。   spec:这是Pod规范部分,用于定义Pod的规范,包括容器的定义。     containers:这是容器列表,包含了Pod中的容器的定义。在这个示例中,只有一个容器,名称为 lifecycle-demo-container,并且它使用了Nginx镜像。    lifecycle:这是定义容器生命周期钩子的部分。在这个示例中,有两个生命周期钩子:         postStart:这是在容器启动后执行的钩子。它使用exec来执行一个命令,即在容器启动后向 /usr/share/message 文件中写入一条消息,消息内容是 “Hello from the postStart handler”。       preStop:这是在容器终止之前执行的钩子。它使用exec来执行一个命令,即在容器终止前通过执行 /usr/sbin/nginx -s quit 命令来优雅地停止Nginx服务。这个YAML文件定义了一个带有生命周期钩子的Pod,这些钩子将在容器启动和终止时执行特定的操作。这可以用来执行初始化或清理任务,以确保容器在启动和终止时执行所需的操作。进入pod内查看输出kubectl exec -it lifecycle-demo -c lifecycle-demo-container -- /bin/sh您运行的命令是 kubectl exec,它用于在Kubernetes中的一个正在运行的Pod中的容器中执行一个特定的命令。下面是您运行的命令的详细解释:kubectl:这是Kubernetes命令行工具,用于与Kubernetes集群进行交互。exec:这是kubectl的一个子命令,用于在一个容器中执行命令。-it:这是kubectl exec命令的标志,它表示您要与命令的标准输入和标准输出进行交互(Interactive Terminal)。这使您可以与容器中的命令进行交互,就像在本地终端中一样。lifecycle-demo:这是要在其中执行命令的Pod的名称。-c lifecycle-demo-container:这是kubectl exec命令的另一个标志,它指定了要在哪个容器中执行命令。在这种情况下,您指定了 lifecycle-demo-container,这是Pod中唯一的容器名称。-- /bin/sh:这是您要在容器中执行的实际命令。它启动一个Shell(/bin/sh),这将允许您在容器中交互式地执行命令。当您运行这个命令后,您将进入 lifecycle-demo-container 中的Shell,从那里您可以执行各种命令,与容器内部进行交互,检查容器中的文件和状态,以及进行其他与容器相关的操作。这对于调试和管理容器非常有用。postStart 在容器创建之后(但并不能保证钩子会在容器 ENTRYPOINT 之前)执行,这时候 Pod 已经被调度到某台 node 上,被某个 kubelet 管理了,这时候 kubelet 会调用 postStart 操作,该操作跟容器的启动命令是在同步执行的,也就是说在 postStart 操作执行完成之前,kubelet 会锁住容器,不让应用程序的进程启动,只有在 postStart 操作完成之后容器的状态才会被设置成为 RUNNING。PreStop 在容器终止之前被同步阻塞调用,常用于在容器结束前优雅的释放资源。如果 postStart 或者 preStop hook 失败,将会终止容器。pod preset(1.11-19 可用 1.20取消了此功能)Pod Preset(Pod配置)是Kubernetes中的一个功能,允许您定义一组默认的环境变量、卷挂载和其他Pod配置,并将它们自动注入到Pod的容器中。这对于自动化和简化Pod配置非常有用,特别是当您需要在多个Pod中使用相同的配置时。以下是有关Pod Preset的详细解释:1.定义默认配置:Pod Preset允许您在Kubernetes中定义默认的配置,包括环境变量、卷挂载、资源限制、资源请求等等。2.命名空间范围:Pod Preset在特定的命名空间内生效,这意味着您可以在每个命名空间内定义不同的配置。3.注入配置:一旦您定义了Pod Preset,Kubernetes将根据Pod的标签选择合适的Preset,并将Preset中定义的配置注入到Pod的容器中。这可以在Pod规范中自动完成,而不需要手动添加每个配置。4.标签选择器:您可以使用标签选择器来将Pod Preset应用于特定的Pod。这意味着您可以选择哪些Pod将使用Preset中定义的配置。5.继承:Pod Preset支持继承,这意味着一个Pod可以继承多个Preset中的配置,从而使配置更加灵活。以下是一个简单的示例,演示如何创建一个Pod Preset并将其应用于Pod:apiVersion: settings.k8s.io/v1alpha1 kind: PodPreset metadata: name: my-pod-preset spec: selector: matchLabels: role: frontend env: - name: DATABASE_URL value: "mysql://mydbserver:3306" volumeMounts: - name: config-volume mountPath: /etc/config volumes: - name: config-volume configMap: name: my-config 在这个示例中,我们创建了一个名为 my-pod-preset 的Pod Preset,它将适用于具有 role: frontend 标签的Pod。这个Preset定义了一个环境变量 DATABASE_URL,一个卷挂载,以及一个与ConfigMap my-config 相关的卷。一旦Preset定义完毕,任何带有 role: frontend 标签的Pod都将自动继承这些配置。Pod Preset对于简化和自动化Pod配置非常有用,特别是在需要共享相似配置的多个Pod的情况下。您可以创建一次配置,并将其应用于多个Pod,以减少重复工作并确保配置的一致性。要使用定义好的Pod Preset YAML 文件,您需要执行以下步骤:1.创建 Pod Preset:首先,您需要将定义的 Pod Preset YAML 文件应用到您的 Kubernetes 集群中。您可以使用 kubectl create 或 kubectl apply 命令来创建 Pod Preset。例如:kubectl create -f your-pod-preset.yaml或kubectl apply -f your-pod-preset.yaml这将在集群中创建名为 my-pod-preset 的 Pod Preset。2.应用 Pod Preset 到 Pod:要将 Pod Preset 应用到 Pod,您需要确保将 Pod 的标签匹配到 Pod Preset 的选择器条件。在您的 Pod YAML 文件中,确保您的 Pod 具有与 Pod Preset 选择器条件匹配的标签。例如,如果您的 Pod 需要使用 my-pod-preset,则可以在 Pod 的标签中添加 role: frontend,以匹配 Pod Preset 的选择器条件。apiVersion: v1 kind: Pod metadata: name: my-pod labels: role: frontend # 匹配 Pod Preset 的选择器条件 spec: containers: - name: my-container image: my-image在这个示例中,role: frontend 标签将与 my-pod-preset 匹配,因此 Pod 将自动继承 Pod Preset 中定义的配置。3.部署 Pod:使用 kubectl apply -f your-pod.yaml 或 kubectl create -f your-pod.yaml 部署 Pod,确保它具有匹配 Pod Preset 的标签。4.验证配置:一旦 Pod 被部署,您可以验证配置是否正确注入到 Pod 中。可以通过执行 kubectl describe pod your-pod 命令来检查 Pod 的详细信息,以查看配置是否正确注入。注意事项:Pod Preset 是 Kubernetes 的扩展功能,确保您的集群支持 Pod Preset。某些 Kubernetes 发行版可能需要启用 Pod Preset 支持。Pod Preset 通常在 Pod 创建时才会应用,如果您想更新一个正在运行的 Pod 的配置,通常需要删除并重新创建该 Pod。Pod Preset 只在同一命名空间内生效,确保 Pod Preset 和要应用它的 Pod 在同一命名空间内。需要管理员或具有足够权限的用户才能创建 Pod Preset。pod优先级和抢占Pod 可以有优先级。 优先级表示一个 Pod 相对于其他 Pod 的重要性。 如果一个 Pod 无法被调度,调度程序会尝试抢占(驱逐)较低优先级的 Pod, 以使悬决 Pod 可以被调度。警告:在一个并非所有用户都是可信的集群中,恶意用户可能以最高优先级创建 Pod, 导致其他 Pod 被驱逐或者无法被调度。 管理员可以使用 ResourceQuota 来阻止用户创建高优先级的 Pod。 参见默认限制优先级消费。创建优先级和抢占新增一个或多个 PriorityClass。创建 Pod,并将其 priorityClassName 设置为新增的 PriorityClass。 当然你不需要直接创建 Pod;通常,你将会添加 priorityClassName 到集合对象(如 Deployment) 的 Pod 模板中。PriorityClass清单apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: high-priority value: 1000000 globalDefault: false description: "此优先级类应仅用于 XYZ 服务 Pod。"声明清单[root@k8smaster priority]# kubectl apply -f priority.yaml查看详情[root@k8smaster priority]# kubectl get PriorityClass NAME VALUE GLOBAL-DEFAULT AGE high-priority 1000000 false 24s system-cluster-critical 2000000000 false 27d system-node-critical 2000001000 false 27dPriorityClassPriorityClass 是 Kubernetes 中的一个无命名空间对象,用于定义从优先级类名称到优先级整数值的映射。PriorityClass 对象有一些关键属性:1.名称(Name): 在 PriorityClass 对象的元数据 name 字段中指定。这个名称必须是有效的 DNS 子域名,而且不能以 “system-” 为前缀。2.值(Value): 在 value 字段中指定,是一个必填字段。这个值表示优先级整数,而且值越大,优先级越高。PriorityClass 对象的值范围是从 -2,147,483,648 到 1,000,000,000。3.全局默认(Global Default): PriorityClass 对象可以有一个可选字段 globalDefault,如果设置为 true,表示这个 PriorityClass 的值应该用于没有指定 priorityClassName 的 Pod。一个集群中只能存在一个 globalDefault 设置为 true 的 PriorityClass。如果没有设置 globalDefault 的 PriorityClass,那么没有指定 priorityClassName 的 Pod 的优先级为零。4.描述(Description): PriorityClass 还有一个可选字段 description,是一个任意字符串,用于提供关于此 PriorityClass 何时应该使用的描述。注意事项如果你升级一个已经存在但尚未使用 PodPriority 特性的 Kubernetes 集群,以及在集群中已经存在的 Pod,以下是一些注意事项:1.已存在 Pod 的优先级等效于零:对于已经存在的 Pod,它们的优先级等效于零,即它们不受 PodPriority 的影响。PodPriority 特性的引入并不会自动改变现有 Pod 的优先级。2.添加 globalDefault 为 true 的 PriorityClass:如果你添加一个 globalDefault 设置为 true 的 PriorityClass,它将成为全局默认的优先级类。然而,这并不会改变已经存在 Pod 的优先级。这个全局默认的优先级类的值仅用于添加 PriorityClass 后创建的 Pod。3.删除 PriorityClass 对象:如果你删除一个 PriorityClass 对象,已存在 Pod 使用被删除的 PriorityClass 名称的优先级仍然保持不变。但是,你将不能再创建使用已删除的 PriorityClass 名称的新 Pod。这是因为删除 PriorityClass 并不会影响已经存在 Pod 的优先级,但不再允许新 Pod 使用这个已删除的 PriorityClass。这些注意事项有助于理解在升级和修改 PriorityClass 设置时,现有 Pod 的行为和影响。PriorityClass示例apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: high-priority value: 1000000 globalDefault: false description: "此优先级类应仅用于 XYZ 服务 Pod。"apiVersion: scheduling.k8s.io/v1: 指定了 PriorityClass 对象的 API 版本,表明使用的是 Kubernetes 调度 API 的版本。kind: PriorityClass: 定义了资源的优先级类别。metadata: 包含了优先级类别对象的元数据,如名称等。    name: high-priority: 设置了优先级类别的名称为 “high-priority”。value: 1000000: 定义了该优先级类别的优先级值。在这里,设置为 1000000,表示较高的优先级。该数值用于在调度中进行优先级比较。globalDefault: false: 指定该优先级类别不是全局默认的。即使不是全局默认,你仍然可以将该优先级类别分配给具体的 Pod。description: "此优先级类应仅用于 XYZ 服务 Pod。": 提供了对该优先级类别用途的描述。在这个例子中,建议将此优先级类别仅用于 XYZ 服务 Pod,以提供更多关于如何使用该优先级类别的信息。非抢占式 PriorityClass(1.24)配置了 preemptionPolicy: Never 的 Pod 将被放置在调度队列中较低优先级 Pod 之前, 但它们不能抢占其他 Pod。等待调度的非抢占式 Pod 将留在调度队列中,直到有足够的可用资源, 它才可以被调度。非抢占式 Pod,像其他 Pod 一样,受调度程序回退的影响。 这意味着如果调度程序尝试这些 Pod 并且无法调度它们,它们将以更低的频率被重试, 从而允许其他优先级较低的 Pod 排在它们之前。非抢占式 Pod 仍可能被其他高优先级 Pod 抢占。preemptionPolicy 默认为 PreemptLowerPriority, 这将允许该 PriorityClass 的 Pod 抢占较低优先级的 Pod(现有默认行为也是如此)。 如果 preemptionPolicy 设置为 Never,则该 PriorityClass 中的 Pod 将是非抢占式的。数据科学工作负载是一个示例用例。用户可以提交他们希望优先于其他工作负载的作业, 但不希望因为抢占运行中的 Pod 而导致现有工作被丢弃。 设置为 preemptionPolicy: Never 的高优先级作业将在其他排队的 Pod 之前被调度, 只要足够的集群资源“自然地”变得可用。非抢占式 PriorityClass 示例apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: high-priority-nonpreempting value: 1000000 preemptionPolicy: Never globalDefault: false description: "This priority class will not cause other pods to be preemptpod优先级一旦你创建了一个或多个 PriorityClass 对象,你可以在创建 Pod 时引用这些优先级类别。Pod 的 priorityClassName 字段用于指定 Pod 使用的优先级类别的名称。在以下示例中,我们使用了先前创建的 PriorityClass 名称为 “high-priority” 的优先级类别:apiVersion: v1 kind: Pod metadata: name: nginx labels: env: test spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent priorityClassName: high-priority这个 Pod 的配置中,priorityClassName 字段被设置为 “high-priority”,这意味着该 Pod 将使用名为 “high-priority” 的 PriorityClass 的优先级。对应的 PriorityClass 对象具有一个整数值为 1000000 的优先级。当这个 Pod 被创建时,优先级准入控制器将检查 PriorityClass 并将其优先级解析为 1000000。如果在集群中找不到指定名称的 PriorityClass,将拒绝创建该 Pod。这有助于确保只有已定义的优先级类别才能用于 Pod 的调度。Pod 优先级对调度顺序的影响当启用 Pod 优先级时,调度程序会按优先级对悬决 Pod 进行排序, 并且每个悬决的 Pod 会被放置在调度队列中其他优先级较低的悬决 Pod 之前。 因此,如果满足调度要求,较高优先级的 Pod 可能会比具有较低优先级的 Pod 更早调度。 如果无法调度此类 Pod,调度程序将继续并尝试调度其他较低优先级的 Pod。抢占Pod 被创建后会进入队列等待调度。 调度器从队列中挑选一个 Pod 并尝试将它调度到某个节点上。 如果没有找到满足 Pod 的所指定的所有要求的节点,则触发对悬决 Pod 的抢占逻辑。 让我们将悬决 Pod 称为 P。抢占逻辑试图找到一个节点, 在该节点中删除一个或多个优先级低于 P 的 Pod,则可以将 P 调度到该节点上。 如果找到这样的节点,一个或多个优先级较低的 Pod 会被从节点中驱逐。 被驱逐的 Pod 消失后,P 可以被调度到该节点上。用户暴露的信息当 Pod P 抢占节点 N 上的一个或多个 Pod 时, Pod P 状态的 nominatedNodeName 字段被设置为节点 N 的名称。 该字段帮助调度程序跟踪为 Pod P 保留的资源,并为用户提供有关其集群中抢占的信息。请注意,Pod P 不一定会调度到“被提名的节点(Nominated Node)”。 调度程序总是在迭代任何其他节点之前尝试“指定节点”。 在 Pod 因抢占而牺牲时,它们将获得体面终止期。 如果调度程序正在等待牺牲者 Pod 终止时另一个节点变得可用, 则调度程序可以使用另一个节点来调度 Pod P。 因此,Pod 规约中的 nominatedNodeName 和 nodeName 并不总是相同。 此外,如果调度程序抢占节点 N 上的 Pod,但随后比 Pod P 更高优先级的 Pod 到达, 则调度程序可能会将节点 N 分配给新的更高优先级的 Pod。 在这种情况下,调度程序会清除 Pod P 的 nominatedNodeName。 通过这样做,调度程序使 Pod P 有资格抢占另一个节点上的 Pod。指定节点和实际节点可能不一致,原因:在指点节点的体面终止值存在更合适的点(时间来的更早)抢占的限制被抢占牺牲者的体面终止当 Pod 被抢占时,牺牲者会得到他们的 体面终止期。 它们可以在体面终止期内完成工作并退出。如果它们不这样做就会被杀死。 这个体面终止期在调度程序抢占 Pod 的时间点和待处理的 Pod § 可以在节点 (N) 上调度的时间点之间划分出了一个时间跨度。 同时,调度器会继续调度其他待处理的 Pod。当牺牲者退出或被终止时, 调度程序会尝试在待处理队列中调度 Pod。 因此,调度器抢占牺牲者的时间点与 Pod P 被调度的时间点之间通常存在时间间隔。 为了最小化这个差距,可以将低优先级 Pod 的体面终止时间设置为零或一个小数字。支持 PodDisruptionBudget,但不保证PodDisruptionBudget (PDB) 允许多副本应用程序的所有者限制因自愿性质的干扰而同时终止的 Pod 数量。 Kubernetes 在抢占 Pod 时支持 PDB,但对 PDB 的支持是基于尽力而为原则的。 调度器会尝试寻找不会因被抢占而违反 PDB 的牺牲者,但如果没有找到这样的牺牲者, 抢占仍然会发生,并且即使违反了 PDB 约束也会删除优先级较低的 Pod。与低优先级 Pod 之间的 Pod 间亲和性只有当这个问题的答案是肯定的时,才考虑在一个节点上执行抢占操作: “如果从此节点上删除优先级低于悬决 Pod 的所有 Pod,悬决 Pod 是否可以在该节点上调度?”说明:抢占并不一定会删除所有较低优先级的 Pod。 如果悬决 Pod 可以通过删除少于所有较低优先级的 Pod 来调度, 那么只有一部分较低优先级的 Pod 会被删除。 即便如此,上述问题的答案必须是肯定的。 如果答案是否定的,则不考虑在该节点上执行抢占。如果悬决 Pod 与节点上的一个或多个较低优先级 Pod 具有 Pod 间亲和性, 则在没有这些较低优先级 Pod 的情况下,无法满足 Pod 间亲和性规则。 在这种情况下,调度程序不会抢占节点上的任何 Pod。 相反,它寻找另一个节点。调度程序可能会找到合适的节点, 也可能不会。无法保证悬决 Pod 可以被调度。我们针对此问题推荐的解决方案是仅针对同等或更高优先级的 Pod 设置 Pod 间亲和性。悬挂 Pod 具有 Pod 间亲和性规则:悬挂 Pod 与某些较低优先级的 Pod 具有 Pod 间亲和性规则,意味着它希望与这些 Pod 共同存在于同一节点上。跨节点抢占假设正在考虑在一个节点 N 上执行抢占,以便可以在 N 上调度待处理的 Pod P。 只有当另一个节点上的 Pod 被抢占时,P 才可能在 N 上变得可行。 下面是一个例子:调度器正在考虑将 Pod P 调度到节点 N 上。Pod Q 正在与节点 N 位于同一区域的另一个节点上运行。Pod P 与 Pod Q 具有 Zone 维度的反亲和(topologyKey:topology.kubernetes.io/zone)设置。Pod P 与 Zone 中的其他 Pod 之间没有其他反亲和性设置。为了在节点 N 上调度 Pod P,可以抢占 Pod Q,但调度器不会进行跨节点抢占。 因此,Pod P 将被视为在节点 N 上不可调度。如果将 Pod Q 从所在节点中移除,则不会违反 Pod 间反亲和性约束, 并且 Pod P 可能会被调度到节点 N 上。如果有足够的需求,并且如果我们找到性能合理的算法, 我们可能会考虑在未来版本中添加跨节点抢占。Pod P 与 Pod Q 具有 Zone 维度的反亲和性:这表示 Pod P 和 Pod Q 不希望在同一 Zone 中运行。这可能是为了提高容错性,确保它们在不同的可用性区域运行,以防发生某种故障。故障排除Pod 优先级和抢占可能会产生不必要的副作用。以下是一些潜在问题的示例以及处理这些问题的方法。Pod 被不必要地抢占抢占在资源压力较大时从集群中删除现有 Pod,为更高优先级的悬决 Pod 腾出空间。 如果你错误地为某些 Pod 设置了高优先级,这些无意的高优先级 Pod 可能会导致集群中出现抢占行为。 Pod 优先级是通过设置 Pod 规约中的 priorityClassName 字段来指定的。 优先级的整数值然后被解析并填充到 podSpec 的 priority 字段。为了解决这个问题,你可以将这些 Pod 的 priorityClassName 更改为使用较低优先级的类, 或者将该字段留空。默认情况下,空的 priorityClassName 解析为零。当 Pod 被抢占时,集群会为被抢占的 Pod 记录事件。只有当集群没有足够的资源用于 Pod 时, 才会发生抢占。在这种情况下,只有当悬决 Pod(抢占者)的优先级高于受害 Pod 时才会发生抢占。 当没有悬决 Pod,或者悬决 Pod 的优先级等于或低于牺牲者时,不得发生抢占。 如果在这种情况下发生抢占,请提出问题。有 Pod 被抢占,但抢占者并没有被调度当 Pod 被抢占时,它们会收到请求的体面终止期,默认为 30 秒。 如果受害 Pod 在此期限内没有终止,它们将被强制终止。 一旦所有牺牲者都离开,就可以调度抢占者 Pod。在抢占者 Pod 等待牺牲者离开的同时,可能某个适合同一个节点的更高优先级的 Pod 被创建。 在这种情况下,调度器将调度优先级更高的 Pod 而不是抢占者。这是预期的行为:具有较高优先级的 Pod 应该取代具有较低优先级的 Pod。优先级较高的 Pod 在优先级较低的 Pod 之前被抢占调度程序尝试查找可以运行悬决 Pod 的节点。如果没有找到这样的节点, 调度程序会尝试从任意节点中删除优先级较低的 Pod,以便为悬决 Pod 腾出空间。 如果具有低优先级 Pod 的节点无法运行悬决 Pod, 调度器可能会选择另一个具有更高优先级 Pod 的节点(与其他节点上的 Pod 相比)进行抢占。 牺牲者的优先级必须仍然低于抢占者 Pod。当有多个节点可供执行抢占操作时,调度器会尝试选择具有一组优先级最低的 Pod 的节点。 但是,如果此类 Pod 具有 PodDisruptionBudget,当它们被抢占时, 则会违反 PodDisruptionBudget,那么调度程序可能会选择另一个具有更高优先级 Pod 的节点。当存在多个节点抢占且上述场景均不适用时,调度器会选择优先级最低的节点。Pod 优先级和服务质量之间的相互作用Pod 优先级和 QoS 类 是两个正交特征,交互很少,并且对基于 QoS 类设置 Pod 的优先级没有默认限制。 调度器的抢占逻辑在选择抢占目标时不考虑 QoS。 抢占会考虑 Pod 优先级并尝试选择一组优先级最低的目标。 仅当移除优先级最低的 Pod 不足以让调度程序调度抢占式 Pod, 或者最低优先级的 Pod 受 PodDisruptionBudget 保护时,才会考虑优先级较高的 Pod。kubelet 使用优先级来确定 节点压力驱逐 Pod 的顺序。 你可以使用 QoS 类来估计 Pod 最有可能被驱逐的顺序。kubelet 根据以下因素对 Pod 进行驱逐排名:1.对紧俏资源的使用是否超过请求值2。Pod 优先级3.相对于请求的资源使用量有关更多详细信息,请参阅 kubelet 驱逐时 Pod 的选择。当某 Pod 的资源用量未超过其请求时,kubelet 节点压力驱逐不会驱逐该 Pod。 如果优先级较低的 Pod 的资源使用量没有超过其请求,则不会被驱逐。 另一个优先级较高且资源使用量超过其请求的 Pod 可能会被驱逐。NodeNode 的状态Node 包括如下状态信息:Address    HostName:可以被 kubelet 中的 --hostname-override 参数替代。    ExternalIP:可以被集群外部路由到的 IP 地址。    InternalIP:集群内部使用的 IP,集群外部无法访问。Condition    OutOfDisk:磁盘空间不足时为 True    Ready:Node controller 40 秒内没有收到 node 的状态报告为 Unknown,健康为 True,否则为 False。    MemoryPressure:当 node 有内存压力时为 True,否则为 False。    DiskPressure:当 node 有磁盘压力时为 True,否则为 False。Capacity    CPU    内存    可运行的最大 Pod 个数Info:节点的一些版本信息,如 OS、kubernetes、docker 等Node 管理禁止 Pod 调度到该节点上。kubectl cordon <node>驱逐该节点上的所有 Pod。kubectl drain <node>该命令会删除该节点上的所有 Pod(DaemonSet 除外),在其他 node 上重新启动它们,通常该节点需要维护时使用该命令。直接使用该命令会自动调用kubectl cordon <node>命令。当该节点维护完成,启动了 kubelet 后,再使用kubectl uncordon <node> 即可将该节点添加到 kubernetes 集群中。问题删除了node怎么重新加入1.Docker 容器运行时未启动:错误信息中显示 Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?,这表明 Docker 容器运行时未启动。2.kubelet 配置文件已存在:错误信息中显示 /etc/kubernetes/kubelet.conf already exists,这表示 kubelet 配置文件已经存在,可能是由于之前的加入尝试导致的。3.启动 Docker 服务:systemctl start docker.service systemctl enable docker.service4.删除已存在的 kubelet 配置文件:sudo rm /etc/kubernetes/kubelet.conf5.重置节点,删除 Kubernetes 相关配置和数据 kubeadm reset6.在maste查看加入加入命令node执行 kubeadm 加入命令:kubeadm token create --print-join-command #查看命令 kubeadm join 192.168.2.210:6443 --token l2kvho.a4qottxzcnuzm99x --discovery-token-ca-cert-hash sha256:6253b7c03d20c41bcaa1585740168ba76deea54ddbc7f2c6ec71d636acb34bca 执行了上面的命令最开始都事好的,随后就NotReady了[root@k8smaster1 ~]# kubectl get node NAME STATUS ROLES AGE VERSION k8smaster Ready control-plane,master 3h38m v1.20.6 k8snode1 NotReady worker 8m11s v1.20.6 k8snode2 Ready worker 3h27m v1.20.6问题所在[root@k8smaster1 ~]# kubectl get pod -n kube-system NAME READY STATUS RESTARTS AGE calico-kube-controllers-6949477b58-5g9g9 1/1 Running 0 3h25m calico-node-762tq 0/1 Running 0 3h25m calico-node-s794v 0/1 CrashLoopBackOff 59 3h25m calico-node-vkbt6 0/1 Running 0 15m coredns-7f89b7bc75-69kjz 1/1 Running 0 16m coredns-7f89b7bc75-zkdrw 1/1 Running 0 3h45m etcd-k8smaster 1/1 Running 0 3h45m kube-apiserver-k8smaster 1/1 Running 0 3h45m kube-controller-manager-k8smaster 1/1 Running 0 3h45m kube-proxy-2jbvz 1/1 Running 0 3h45m kube-proxy-794kj 1/1 Running 0 15m kube-proxy-g4g2f 1/1 Running 0 3h34m kube-scheduler-k8smaster 1/1 Running 0 3h45m如何回滚k8s升级的问题?降级k8sCentOS软件降级操作如下:首先查看软件升级的事务ID:yum history list all根据ID查看变更的内容:yum history info ID确认ID确认,执行回滚操作:yum history undo ID[root@k8smaster ~]# yum history info 6已加载插件:fastestmirror事务 ID: 6起始时间 : Thu Mar 23 17:22:20 2023启动 RPM 数据库 : 432:d9b0370070fa41485e6e95bcd666c64590af68c2结束时间 : 17:22:31 2023 (11 秒)结束 RPM 数据库 : 437:0c6f05ddaaf2432092702713a3fbbf0eea054b29用户 : root返回码 : 成功命令行 : install -y kubelet-1.20.6 kubeadm-1.20.6 kubectl-1.20.6事务完成属主:已安装 rpm-4.11.3-45.el7.x86_64 @anaconda已安装 yum-3.4.3-168.el7.centos.noarch @anaconda已安装 yum-metadata-parser-1.1.4-10.el7.x86_64 @anaconda已安装 yum-plugin-fastestmirror-1.1.31-54.el7_8.noarch @anaconda已变更的包:依赖安装 cri-tools-1.26.0-0.x86_64 @kubernetes安装 kubeadm-1.20.6-0.x86_64 @kubernetes安装 kubectl-1.20.6-0.x86_64 @kubernetes安装 kubelet-1.20.6-0.x86_64 @kubernetes依赖安装 kubernetes-cni-1.2.0-0.x86_64 @kuberneteshistory info
0
0
0
浏览量2016
锅从天上来

K8S(八)—有、无状态.md

无状态在Kubernetes(k8s)中,"无状态"通常指的是应用程序的设计方式,其中应用程序实例之间的状态不共享,并且可以在需要时水平扩展。无状态应用程序不依赖于本地存储或会话信息,使它们更容易部署、扩展和管理。在Kubernetes中,无状态应用程序可以通过部署多个相同的副本,以实现负载均衡和高可用性。以下是在Kubernetes中创建无状态应用程序的一般步骤和一些相关的概念:容器化应用程序: 首先,将应用程序容器化,将应用程序和其依赖项打包到容器中。这通常涉及创建一个Docker镜像。声明性配置: 使用Kubernetes的声明性配置,定义应用程序的规范,包括所需的容器镜像、副本数等。这可以通过YAML文件完成。副本集(ReplicaSet): 通过创建一个ReplicaSet对象,指定所需的副本数。ReplicaSet确保在集群中运行指定数量的副本,并在发生故障时进行自动修复。apiVersion: apps/v1 kind: ReplicaSet metadata: name: example-app spec: replicas: 3 selector: matchLabels: app: example template: metadata: labels: app: example spec: containers: - name: app-container image: example-image:latest服务(Service): 为无状态应用程序创建一个Service,它为副本集提供一个稳定的网络终结点。Service允许其他应用程序通过Service的虚拟IP和端口与应用程序通信。apiVersion: v1 kind: Service metadata: name: example-service spec: selector: app: example ports: - protocol: TCP port: 80 targetPort: 8080水平扩展: 通过更改ReplicaSet中的副本数,可以水平扩展应用程序,以适应不同的负载。Kubernetes会自动管理副本的创建和销毁。通过这些步骤,你可以在Kubernetes中创建一个无状态应用程序,它可以以水平扩展的方式运行,并通过服务提供稳定的网络终结点。这种设计使得应用程序更容易维护和扩展,同时提供高可用性。有状态(StatefulSet)介绍出现这种问题的原因可能是由于两种不同的环境或网络配置所致。让我们分析一下可能的原因以及如何解决这个问题:DNS配置不同:在第一个命令中,您在Kubernetes主机上运行了nslookup命令,并且DNS服务器配置正确,所以它成功解析了 “web-1.nginx.default.svc.cluster.local”。在第二个命令中,您在一个BusyBox容器内运行了nslookup命令,该容器可能没有正确配置的DNS服务器信息,或者可能没有与Kubernetes集群内部DNS服务器通信的网络访问权限。网络问题:确保BusyBox容器内部的网络配置是正确的,能够与Kubernetes集群的DNS服务器进行通信。如果容器无法访问Kubernetes DNS服务器,它将无法解析服务名称。您可以尝试运行nslookup命令时指定DNS服务器的IP地址,例如:nslookup web-1.nginx.default.svc.cluster.local 10.96.0.10,这将明确指定DNS服务器来解析名称,以确保DNS服务器的正确配置。DNS缓存问题:如果在BusyBox容器内部多次运行nslookup并且之前有解析失败的尝试,可能会出现DNS缓存问题。您可以尝试清除DNS缓存,然后再次运行nslookup。Service名称错误:确保Service的名称 “nginx” 和命令中的名称匹配。检查是否有任何拼写错误或大小写问题。Kubernetes集群问题:检查Kubernetes集群的状态,确保所有组件都在正常运行。DNS解析依赖于Kubernetes DNS服务的正常工作。请首先检查上述问题,特别是在容器内部的网络和DNS配置。如果问题仍然存在,请提供更多有关您的环境配置和日志信息,以便更深入地分析和解决问题。应用创建web.yamlapiVersion: v1 kind: Service metadata: name: nginx labels: app: nginx spec: ports: - port: 80 name: web clusterIP: None selector: app: nginx --- apiVersion: apps/v1 kind: StatefulSet metadata: name: web spec: serviceName: "nginx" replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent ports: - containerPort: 80 name: web这是一个Kubernetes配置文件,用于创建一个Service和一个StatefulSet,这两者都用于部署和管理NGINX应用。以下是对配置文件中各部分的详细解释:Service部分:apiVersion: v1 和 kind: Service 表明这是一个Kubernetes Service 资源。metadata 包含有关Service的元数据,包括名称和标签。name: nginx 定义了Service的名称为 “nginx”。labels 定义了标签,其中 app: nginx 将该Service与后面的StatefulSet关联起来。spec 定义了Service的规格。    ports 定义了Service监听的端口,这里监听端口80,并且命名为 “web”。    clusterIP: None 意味着这是一个Headless Service,不会分配Cluster IP。StatefulSet部分:apiVersion: apps/v1 和 kind: StatefulSet 表明这是一个Kubernetes StatefulSet 资源。metadata 包含有关StatefulSet的元数据,包括名称。name: web 定义了StatefulSet的名称为 “web”。spec 定义了StatefulSet的规格。     serviceName: "nginx" 指定了StatefulSet关联的Service的名称,这将允许StatefulSet的Pods在DNS中使用 “nginx” 作为服务名。     replicas: 3 指定了要创建的Pod副本数,这里是3个。    selector 指定了用于选择要管理的Pod的标签。        matchLabels 定义了标签选择器,它与Service的标签匹配,以确保StatefulSet管理的是Service的Pod。    template 定义了要创建的Pod的模板。        metadata 包含有关Pod模板的元数据,包括标签。            labels 标签与Service的标签匹配,以确保Pod与Service关联。    spec 定义了Pod的规格。        containers 定义了容器列表。            name: nginx 定义了容器的名称为 “nginx”。            image: nginx 指定要使用的NGINX镜像。            imagePullPolicy: IfNotPresent 意味着在本地不存在NGINX镜像时才拉取。            ports 定义了容器监听的端口,这里监听端口80,并且命名为 “web”。这个配置文件创建了一个Headless Service(Cluster IP为None)以及一个StatefulSet,该StatefulSet使用NGINX容器创建3个Pod,并将它们关联到该Service上,以便通过Service名称 “nginx” 在集群内部访问这些Pod。这种设置通常用于需要有状态应用程序,因为StatefulSet可以为每个Pod分配唯一的标识,并提供有序的部署和伸缩机制。[root@k8smaster Stateful]# kubectl apply -f web.yaml [root@k8smaster Stateful]# kubectl get pod NAME READY STATUS RESTARTS AGE web-0 1/1 Running 0 81s web-1 1/1 Running 0 79s web-2 1/1 Running 0 76s [root@k8smaster Stateful]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 2d22h mynginx NodePort 10.103.164.206 <none> 80:30009/TCP 2d18h mysql-service NodePort 10.109.26.85 <none> 3360:30008/TCP 2d18h nginx ClusterIP None <none> 80/TCP 94s [root@k8smaster Stateful]# kubectl get pod -n kube-system NAME READY STATUS RESTARTS AGE calico-kube-controllers-6949477b58-nwmr2 1/1 Running 0 2d19h calico-node-5jq26 1/1 Running 0 2d19h calico-node-lk4zv 1/1 Running 0 2d19h calico-node-n4742 1/1 Running 0 2d19h coredns-7f89b7bc75-7zdk5 1/1 Running 0 2d22h 查看**endpoint**[root@k8smaster Stateful]# kubectl get ep NAME ENDPOINTS AGE kubernetes 192.168.2.210:6443 2d22h mynginx <none> 2d18h mysql-service <none> 2d18h nginx 10.244.185.197:80,10.244.249.4:80,10.244.249.5:80 8m37s进入ngixn里[root@k8smaster Stateful]# kubectl exec -it web-1 -- bash root@web-1:/# curl web-1.nginx.default.svc.cluster.local <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> html { color-scheme: light dark; } body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html> 下载bind-utilsyum install bind-utils -y [root@k8smaster Stateful]# nslookup web-1.nginx.default.svc.cluster.local 10.96.0.10Server: 10.96.0.10 Address: 10.96.0.10#53 Name: web-1.nginx.default.svc.cluster.local Address: 10.244.249.4使用 kubectl run 运行一个提供 nslookup 命令的容器,该命令来自于 dnsutils 包。 通过对 Pod 的主机名执行 nslookup,你可以检查这些主机名在集群内部的 DNS 地址:kubectl run -i --tty --image busybox:1.28 dns-test --restart=Never --rm这将启动一个新的 Shell。在新 Shell 中运行:# 在 dns-test 容器 Shell 中运行以下命令 nslookup web-0.nginx输出类似于:Server: 10.0.0.10 Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local Name: web-0.nginx Address 1: 10.244.1.6 nslookup web-1.nginx Server: 10.0.0.10 Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local Name: web-1.nginx Address 1: 10.244.2.6(现在可以退出容器 Shell:exit)应用2以一个简单的nginx服务web.yaml为例:--- apiVersion: v1 kind: Service metadata: name: nginx labels: app: nginx spec: ports: - port: 80 name: web clusterIP: None selector: app: nginx --- apiVersion: apps/v1 kind: StatefulSet metadata: name: nginx # 将StatefulSet的名称改为"nginx" spec: serviceName: "nginx" replicas: 2 selector: matchLabels: app: nginx # 添加选择器以匹配Pod的标签 template: metadata: labels: app: nginx spec: containers: - name: nginx image: gcr.io/google_containers/nginx-slim:0.8 ports: - containerPort: 80 name: web volumeMounts: - name: www mountPath: /usr/share/nginx/html volumeClaimTemplates: - metadata: name: www annotations: volume.alpha.kubernetes.io/storage-class: anything spec: accessModes: [ "ReadWriteOnce" ] resources: requests: storage: 1Gi [root@k8smaster service]# kubectl apply -f statefulsets.yaml service/nginx unchanged statefulset.apps/nginx created # 查看创建的headless service和statefulset [root@k8smaster service]# kubectl get service nginx NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx ClusterIP None <none> 80/TCP 71m 1. 状态持久性:•无状态应用程序: 无状态应用程序通常不需要持久性的存储。它们的每个实例都是相互独立的,可以在需要时动态创建和销毁。无状态应用程序不依赖于本地状态或会话信息。•有状态应用程序: 有状态应用程序需要维护一些持久性的状态或数据,例如数据库。这种状态通常需要在容器重新调度或故障时保持不变。2. 水平扩展:•无状态应用程序: 无状态应用程序可以很容易地进行水平扩展,通过增加或减少实例的数量来处理负载。每个实例都是相同的,可以随意添加或删除。•有状态应用程序: 有状态应用程序的水平扩展可能更为复杂,因为每个实例可能会维护特定的状态。在水平扩展时,需要考虑如何处理和同步状态,以确保应用程序的一致性。3. 存储和卷:•无状态应用程序: 通常,无状态应用程序可以使用临时存储,而无需关心数据的持久性。Kubernetes可以随时重新创建实例,而不会丢失重要数据。•有状态应用程序: 有状态应用程序通常需要使用持久卷(Persistent Volumes)来存储和保护其状态。这确保了即使实例重新调度,应用程序仍然可以访问其之前的状态。4. Pod标识和网络标识:•无状态应用程序: 无状态应用程序通常可以使用随机的Pod标识符,因为它们的实例之间是相互独立的。它们依赖于服务发现机制来实现负载均衡。•有状态应用程序: 有状态应用程序通常需要稳定的网络标识符和主机名,以确保它们在重新调度或扩展时能够保持一致的网络标识。5. 部署和更新:•无状态应用程序: 无状态应用程序的部署和更新通常更加简单,因为新的实例可以替代旧的实例而不会影响整体系统的一致性。•有状态应用程序: 有状态应用程序的部署和更新可能需要更复杂的策略,以确保状态的平滑过渡,例如滚动更新和分阶段部署。总体而言,选择使用有状态或无状态应用程序取决于应用程序的要求和特性。有状态应用程序通常更适合于需要维护持久状态或数据的情况,而无状态应用程序则更适合于可以水平扩展和无状态实例之间相互替换的情况。有状态和无状态对比StatefulSet是为了解决有状态服务的问题(对应Deployments和ReplicaSets是为无状态服务而设计)在Kubernetes(k8s)中,有状态应用程序和无状态应用程序在设计和管理上存在一些关键的区别。下面是有状态和无状态应用程序的详细对比:1. 概念:    有状态应用程序(Stateful Applications):            有状态应用程序通常需要在其生命周期内维护和管理持久状态,例如数据库。            这类应用程序对于节点之间的状态保持和标识是敏感的,通常需要唯一标识符来管理其状态。            有状态应用程序的实例通常被认为是持久性的,它们拥有独特的标识符,比如Pod名称。    无状态应用程序(Stateless Applications):            无状态应用程序不依赖于在其运行时维护的任何持久状态。             这类应用程序的实例是可以互相替代的,因为它们的状态不会影响系统的整体运行。            无状态应用程序通常更容易水平扩展,因为它们的实例之间是相互独立的。2. 数据持久性:    有状态应用程序:            需要对数据进行持久化存储,通常使用持久卷(Persistent Volumes)或其他持久化存储解决方案。            数据通常存储在外部数据库中,而Pod实例只是应用程序的前端。    无状态应用程序:            不需要在本地持久化存储数据,通常将数据存储在外部数据存储或数据库中。3. 扩展性:    有状态应用程序:            扩展有状态应用程序可能更具挑战性,因为每个实例需要维护自己的状态,并且可能需要处理数据同步等问题。    无状态应用程序:            由于无状态应用程序的实例是相互独立的,它们通常更容易水平扩展,可以通过增加实例数量来应对负载增加。4. 管理和部署:    有状态应用程序:            部署和管理有状态应用程序可能需要更多的关注和复杂性,因为需要确保状态的一致性和可靠性。    无状态应用程序:            无状态应用程序通常更容易部署和管理,因为它们的实例可以相对容易地替代彼此。5. 故障恢复:    有状态应用程序:            故障恢复可能需要更多的关注,因为在一个节点故障时,需要确保状态的无缝切换。    无状态应用程序:            由于无状态应用程序的实例是相互独立的,故障恢复通常更为简单,新的实例可以替代故障的实例。在选择有状态或无状态应用程序时,需要考虑应用程序的特性、性能需求和运维复杂性。有时候,应用程序可能会包含既有状态的组件又有无状态的组件,这需要综合考虑和合理设计。
0
0
0
浏览量2011
锅从天上来

【Kubernetes】配置管理中心Secret

一、简介1.1、什么是Secret上面我们学习的Configmap一般是用来存放明文数据的,如配置文件,对于一些敏感数据,如密码、私钥等数据时,要用secret类型。1.2、Secret能解决什么问题Secret解决了密码、token、秘钥等敏感数据的配置问题,而不需要把这些敏感数据暴露到镜像或者Pod Spec中。Secret可以以Volume或者环境变量的方式使用。要使用 secret,pod 需要引用 secret。Pod 可以用两种方式使用 secret:作为 volume 中的文件被挂载到 pod 中的一个或者多个容器里当 kubelet 为 pod 拉取镜像时使用。1.3、Secret可选参数generic: 通用类型,通常用于存储密码数据。tls:此类型仅用于存储私钥和证书。docker-registry: 若要保存docker仓库的认证信息的话,就必须使用此种类型来创建。1.4、Secret类型Service Account用于被 serviceaccount 引用。serviceaccout 创建时 Kubernetes 会默认创建对应的 secret。Pod 如果使用了 serviceaccount,对应的 secret 会自动挂载到 Pod 的 /run/secrets/kubernetes.io/serviceaccount 目录中。Opaquebase64编码格式的Secret,用来存储密码、秘钥等。可以通过base64 --decode解码获得原始数据,因此安全性弱kubernetes.io/dockerconfigjson用来存储私有docker registry的认证信息。二、使用Secret2.1、通过环境变量引入Secret【1】创建secret# 把mysql的root用户的password创建成secret [root@master 15]# cd kubectl create secret generic mysql-password --from-literal=password=xianchaopod**lucky66^C [root@master 15]# ll total 0 [root@master 15]# kubectl create secret generic mysql-password --from-literal=password=123456 secret/mysql-password created [root@master 15]# kubectl get secret NAME TYPE DATA AGE mysql-password Opaque 1 7s [root@master 15]# kubectl describe secret mysql-password Name: mysql-password Namespace: default Labels: <none> Annotations: <none> Type: Opaque Data ==== password: 6 bytes # password的值是加密的, # 但secret的加密是一种伪加密,它仅仅是将数据做了base64的编码.【2】创建pod,引用secret# 创建pod,引用secret [root@master 15]# cat pod-secret.yaml apiVersion: v1 kind: Pod metadata: name: pod-secret labels: app: myapp spec: containers: - name: myapp image: ikubernetes/myapp:v1 ports: - name: http containerPort: 80 env: - name: MYSQL_ROOT_PASSWORD # 它是Pod启动成功后,Pod中容器的环境变量名. valueFrom: secretKeyRef: name: mysql-password # 这是secret的对象名 key: password # 它是secret中的key名 [root@master 15]# kubectl apply -f pod-secret.yaml pod/pod-secret created [root@master 15]# kubectl exec -it pod-secret -- /bin/sh / # printenv ...... MYSQL_ROOT_PASSWORD=123456 2.2、通过volume挂载Secret【1】创建secret手动加密,基于base64加密。[root@master 15]# echo -n 'admin' | base64 YWRtaW4= [root@master 15]# echo -n 'hj666' | base64 aGo2NjY=解码:[root@master 15]# echo aGo2NjY=| base64 -d hj666【2】创建yaml文件[root@master 15]# cat secret.yaml apiVersion: v1 kind: Secret metadata: name: mysecret type: Opaque data: username: YWRtaW4= password: aGo2NjY=[root@master 15]# kubectl apply -f secret.yaml secret/mysecret created [root@master 15]# kubectl describe secret mysecret Name: mysecret Namespace: default Labels: <none> Annotations: <none> Type: Opaque Data ==== password: 5 bytes username: 5 bytes【3】将Secret挂载到Volume中[root@master 15]# cat pod_secret_volume.yaml apiVersion: v1 kind: Pod metadata: name: pod-secret-volume spec: containers: - name: myapp image: registry.cn-beijing.aliyuncs.com/google_registry/myapp:v1 volumeMounts: - name: secret-volume mountPath: /etc/secret readOnly: true volumes: - name: secret-volume secret: secretName: mysecret[root@master 15]# kubectl apply -f pod_secret_volume.yaml pod/pod-secret-volume created [root@master 15]# kubectl exec -it pod-secret-volume -- /bin/sh / # ls /etc/secret password username / # cat /etc/secret/username admin/ # cat /etc/secret/password hj666/ #由上可见,在pod中的secret信息实际已经被解密
0
0
0
浏览量298
锅从天上来

【Kubernetes】存储类StorageClass

一、StorageClass介绍之前介绍的PV和PVC模式都是需要先创建好PV,然后定义好PVC和pv进行一对一的Bond,但是如果PVC请求成千上万,那么就需要创建成千上万的PV,对于运维人员来说维护成本很高,Kubernetes提供一种自动创建PV的机制,叫StorageClass,它的作用就是创建PV的模板。k8s集群管理员通过创建storageclass可以动态生成一个存储卷pv供k8s pvc使用。具体来说,StorageClass会定义以下两部分:=========1、PV的属性 ,比如存储的大小、类型等;2、创建这种PV需要使用到的存储插件,比如Ceph、NFS等=========有了这两部分信息,Kubernetes就能够根据用户提交的PVC,找到对应的StorageClass,然后Kubernetes就会调用 StorageClass声明的存储插件,创建出需要的PV。查看定义的storageclass需要的字段:kubectl explain storageclass每个StorageClass都包含字段provisioner,parameters和reclaimPolicy[root@master 10]# kubectl explain storageclass KIND: StorageClass VERSION: storage.k8s.io/v1 DESCRIPTION: StorageClass describes the parameters for a class of storage for which PersistentVolumes can be dynamically provisioned. StorageClasses are non-namespaced; the name of the storage class according to etcd is in ObjectMeta.Name. FIELDS: allowVolumeExpansion <boolean> allowedTopologies <[]Object> apiVersion <string> kind <string> metadata <Object> mountOptions <[]string> parameters <map[string]string> # 键值对类型 provisioner <string> -required- # 供应商 reclaimPolicy <string> # 回收策略 volumeBindingMode <string>provisioner:供应商,storageclass需要有一个供应者,用来确定我们使用什么样的存储来创建pv,常见的provisioner:(https://kubernetes.io/zh/docs/concepts/storage/storage-classes/)provisioner既可以由内部供应商提供,也可以由外部供应商提供,如果是外部供应商可以参考https://github.com/kubernetes-incubator/external-storage/下提供的方法创建。https://github.com/kubernetes-sigs/sig-storage-lib-external-provisioner以NFS为例,要想使用NFS,我们需要一个nfs-client的自动装载程序,称之为provisioner,这个程序会使用我们已经配置好的NFS服务器自动创建持久卷,也就是自动帮我们创建PV。allowVolumeExpansion:允许卷扩展,PersistentVolume 可以配置成可扩展。将此功能设置为true时,允许用户通过编辑相应的 PVC 对象来调整卷大小。当基础存储类的allowVolumeExpansion字段设置为 true 时,以下类型的卷支持卷扩展。注意:此功能仅用于扩容卷,不能用于缩小卷。二、安装nfs provisioner,用于配合存储类动态生成pv将nfs-subdir-external-provisioner.tar.gz上传到工作节点node01和node02上,然后手动解压。[root@node01 ~]# ctr -n=k8s.io images import nfs-subdir-external-provisioner.tar.gz unpacking registry.cn-beijing.aliyuncs.com/mydlq/nfs-subdir-external-provisioner:v4.0.0 (sha256:69b08b256d7e9f5823cf09dece7eabf025cc60c652e4ae08201978bb2862a276)...done You have new mail in /var/spool/mail/root [root@node02 ~]# ctr -n=k8s.io images import nfs-subdir-external-provisioner.tar.gz unpacking registry.cn-beijing.aliyuncs.com/mydlq/nfs-subdir-external-provisioner:v4.0.0 (sha256:69b08b256d7e9f5823cf09dece7eabf025cc60c652e4ae08201978bb2862a276)...done You have new mail in /var/spool/mail/root2.1、创建运行nfs-provisioner需要的sa账号[root@master 11]# cat serviceaccount.yaml apiVersion: v1 kind: ServiceAccount metadata: name: nfs-provisioner [root@master 11]# kubectl apply -f serviceaccount.yaml serviceaccount/nfs-provisioner created [root@master 11]# kubectl get sa NAME SECRETS AGE default 0 5d13h nfs-provisioner 0 21s扩展:什么是sa?sa的全称是serviceaccount。serviceaccount是为了方便Pod里面的进程调用Kubernetes API或其他外部服务而设计的。指定了serviceaccount之后,我们把pod创建出来了,我们在使用这个pod时,这个pod就有了我们指定的账户的权限了。2.2、对sa授权[root@master 11]# kubectl create clusterrolebinding nfs-provisioner-clusterrolebinding --clusterrole=cluster-admin --serviceaccount=default:nfs-provisioner clusterrolebinding.rbac.authorization.k8s.io/nfs-provisioner-clusterrolebinding created2.3、安装nfs-provisioner程序[root@master 11]# cat /etc/exports /data/volumes 10.32.1.147/24(rw,no_root_squash) /data/volume_test/v1 10.32.1.147/24(rw,no_root_squash) /data/volume_test/v2 10.32.1.147/24(rw,no_root_squash) /data/volume_test/v3 10.32.1.147/24(rw,no_root_squash) /data/volume_test/v4 10.32.1.147/24(rw,no_root_squash) /data/volume_test/v5 10.32.1.147/24(rw,no_root_squash) /data/volume_test/v6 10.32.1.147/24(rw,no_root_squash) /data/volume_test/v7 10.32.1.147/24(rw,no_root_squash) /data/volume_test/v8 10.32.1.147/24(rw,no_root_squash) /data/volume_test/v9 10.32.1.147/24(rw,no_root_squash) /data/volume_test/v10 10.32.1.147/24(rw,no_root_squash) /data/nfs_pro 10.32.1.147/24(rw,no_root_squash) [root@master 11]# exportfs -arv exporting 10.32.1.147/24:/data/nfs_pro exporting 10.32.1.147/24:/data/volume_test/v10 exporting 10.32.1.147/24:/data/volume_test/v9 exporting 10.32.1.147/24:/data/volume_test/v8 exporting 10.32.1.147/24:/data/volume_test/v7 exporting 10.32.1.147/24:/data/volume_test/v6 exporting 10.32.1.147/24:/data/volume_test/v5 exporting 10.32.1.147/24:/data/volume_test/v4 exporting 10.32.1.147/24:/data/volume_test/v3 exporting 10.32.1.147/24:/data/volume_test/v2 exporting 10.32.1.147/24:/data/volume_test/v1 exporting 10.32.1.147/24:/data/volumes[root@master 11]# cat nfs-deployment.yaml kind: Deployment apiVersion: apps/v1 metadata: name: nfs-provisioner spec: selector: matchLabels: app: nfs-provisioner replicas: 1 strategy: type: Recreate template: metadata: labels: app: nfs-provisioner spec: serviceAccount: nfs-provisioner containers: - name: nfs-provisioner image: registry.cn-beijing.aliyuncs.com/mydlq/nfs-subdir-external-provisioner:v4.0.0 imagePullPolicy: IfNotPresent volumeMounts: - name: nfs-client-root mountPath: /persistentvolumes env: - name: PROVISIONER_NAME value: example.com/nfs - name: NFS_SERVER value: 10.32.1.147 - name: NFS_PATH value: /data/nfs_pro/ volumes: - name: nfs-client-root nfs: server: 10.32.1.147 path: /data/nfs_pro/ [root@master 11]# kubectl apply -f nfs-deployment.yaml deployment.apps/nfs-provisioner created [root@master 11]# kubectl get pods | grep nfs nfs-provisioner-d5bd78f66-56ccg 1/1 Running 0 6s三、创建storageclass,动态供给pv[root@master 11]# cat nfs-storageclass.yaml apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: nfs provisioner: example.com/nfs [root@master 11]# kubectl apply -f nfs-storageclass.yaml storageclass.storage.k8s.io/nfs created [root@master 11]# kubectl get storageclass NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE nfs example.com/nfs Delete Immediate false 22s # 显示内容如上,说明storageclass创建成功了注意:provisioner处写的example.com/nfs应该跟安装nfs provisioner时候的env下的PROVISIONER_NAME的value值保持一致,如下:env: - name: PROVISIONER_NAME value: `example.com/nfs`四、创建pvc,通过storageclass动态生成pv[root@master 11]# cat claim.yaml kind: PersistentVolumeClaim apiVersion: v1 metadata: name: test-claim1 spec: accessModes: ["ReadWriteMany"] resources: requests: storage: 1Gi storageClassName: nfs [root@master 11]# kubectl apply -f claim.yaml persistentvolumeclaim/test-claim1 created # 查看是否动态生成了pv,pvc是否创建成功,并和pv绑定 [root@master 11]# kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE test-claim1 Bound pvc-6ecea632-e5ff-4ef9-99df-33638fe90a1c 1Gi RWX nfs 13s # 通过上面可以看到test-claim1的pvc已经成功创建了,绑定的pv是pvc-6ecea632-e5ff-4ef9-99df-33638fe90a1c # 这个pv是由storageclass调用nfs provisioner自动生成的。步骤总结:1、供应商:创建一个nfs provisioner2、创建storageclass,storageclass指定刚才创建的供应商3、创建pvc,这个pvc指定storageclass五、创建pod,挂载storageclass动态生成的pvc[root@master 11]# cat read-pod.yaml kind: Pod apiVersion: v1 metadata: name: read-pod spec: containers: - name: read-pod image: nginx imagePullPolicy: IfNotPresent volumeMounts: - name: nfs-pvc mountPath: /usr/share/nginx/html restartPolicy: "Never" volumes: - name: nfs-pvc persistentVolumeClaim: claimName: test-claim1 [root@master 11]# kubectl apply -f read-pod.yaml pod/read-pod created [root@master 11]# kubectl get pods | grep read read-pod 1/1 Running 0 16s
0
0
0
浏览量2016
锅从天上来

【Kubernetes】认证授权RBAC (一)

一、k8s安全管理:认证、授权、准入控制概述1.1、简介【1】认证基本介绍kubernetes主要通过APIserver对外提供服务,那么就需要对访问apiserver的用户做认证。如果任何人都能访问apiserver,那么就可以随意在k8s集群部署资源,这是非常危险的,也容易被黑客攻击渗透。所以需要我们对访问的k8s系统apiserver的用户进行认证,确保是合法的、符合要求的用户【2】授权基本介绍认证通过后仅代表它是一个被apiserver信任的用户,能访问apierver,但是用户是否拥有删除资源的权限,需要进行授权操作,常见的授权方式有rbac授权。【3】准入控制基本介绍当用户经过认证和授权后,最后一步就是准入控制了。k8s提供了多重准入控制机制,它有点类似“插件”,为apiserver提供了很好的“可扩展性”。请求apiserver时,通过认证鉴权后、持久化(“api对象”保存到etcd)前,会经过“准入控制器”,让它可以做“变更和认证”。为什么需要准入控制器呢?如果我们创建pod时定义了资源上下限,但不满足LimitRange规则中定义的资源上下限,此时LimitRanger就会拒绝我们创建此pod。假如我们定义了一个名称空间叫做test-aa,这个名称空间做下资源限制:限制最多可以使用10vCPU、10Gi内存,在这个名称空间test-aa下创建的所有pod,定义limit的时候,所有pod的limit值不能超过test-aa这个名称空间设置的limit上线。1.2、认证k8s客户端访问apiserver的几种认证方式:【1】客户端认证客户端认证也成为双向TLS认证,kubectl在访问apiserver的时候,apiserver也要认证kubectl是否是合法的,他们都会通过ca根证书来进行验证:【2】BearertokenBeartoken的方式,可以理解为apiserver将一个密码通过了非对称加密的方式告诉了kubectl,然后通过该密码进行相互访问:kubectl访问k8s集群,要找一个kubeconfig文件,基于这个文件里的用户访问apiserver。kubectl访问k8s集群,要找一个kubeconfig文件,基于这个文件里的用户访问apiserver。【3】Serviceaccount上面的俩种认证方式,都是外部访问apiserver的时候使用的方式。serviceaccount是内部访问pod和apiserver交互时候采用的一种方式。serviceaccount包括namespace、token、ca,且通过目录挂载的方式给与pod,当pod运行起来的时候,就会读取到这些信息,从而使用该方式和apiserver进行通信。【4】拓展:kubeconfig文件官方地址:https://kubernetes.io/zh-cn/docs/concepts/configuration/organize-cluster-access-kubeconfig/在k8s集群中,当我们使用kubectl操作k8s资源时,需要确定我们用哪个用户访问哪个k8s集群,kubectl操作k8s集群资源会去/root/.kube目录下找config文件,可以通过命令行查看配置文件:[root@master ~]# kubectl config view apiVersion: v1 clusters: - cluster: certificate-authority-data: DATA+OMITTED server: https://10.32.1.147:6443 # apiserver地址 name: kubernetes # 集群的名字 contexts: - context: cluster: kubernetes user: kubernetes-admin name: kubernetes-admin@kubernetes # 上下文的名字 current-context: kubernetes-admin@kubernetes # 当前上下文 kind: Config preferences: {} users: - name: kubernetes-admin user: client-certificate-data: REDACTED client-key-data: REDACTED在上面的配置文件当中,定义了集群、上下文以及用户。其中config也是k8s的标准资源之一,在该配置文件中定义了一个集群列表,指定的集群可有多个,用户列表也可以有多个,指明集群中的用户。而在上下文列表当中,是进行定义可以使用哪个用户对那个集群进行访问,以及当前使用的上下文是什么。kubectl get pods --kubeconfig=/root/.kube/config1.3、授权用户通过认证之后,什么权限都没有,需要一些后续的授权操作,如对资源的增删该查等,kubernetes1.6之后开始有RBAC(基于角色的访问控制机制)授权检查机制。Kubernetes的授权是基于插件形成的,其常用的授权插件有以下几种:1)Node(节点认证)2)ABAC(基于属性的访问控制)3)RBAC(基于角色的访问控制) ***4)Webhook(基于http回调机制的访问控制)【1】什么是RBAC(基于角色的授权)让一个用户(user)扮演一个角色(Role),角色拥有权限,从而让用户拥有这样的权限,随后在授权机制当中,只需要将权限授予某个角色,此时用户将获取对应角色的权限,从而实现角色的访问。在k8s的授权机制当中,采用RBAC的方式进行授权,其工作逻辑是:把对对象的操作权限定义到一个角色当中,再将用户绑定到该角色,从而使用户得到对应角色的权限。如果通过rolebinding绑定role,只能对rolebinding所在的名称空间的资源有权限。如上图,user1绑定到role1,只对role1这个名称空间的资源有权限,对其他ns的资源无权限,属于名称空间级别的;另外,k8s还有一种集群级别的授权机制,就是定义一个集群角色(ClusterRole),对集群内的所有资源都有课操作的权限。user可以通过ClusterRoleBinding绑定到ClusterRole,从而使user拥有集群的操作权限。【2】用户基于rolebinding绑定到role限定在rolebinding所在的名称空间【3】用户基于rolebinding绑定到clusterrolerolebinding绑定clusterrole的好处:假如有6个ns,每个ns下的用户都需要对自己的名称空间有管理员权限,那么需要定义6个role和rolebinding,然后依次绑定,如果ns越来越多,就要定义更多的role和rolebinding,很麻烦,所以引入clusterrole。定义一个clusterole,对其授予所有权限,然后用户通过rolebinding绑定到clusterrole,就会拥堵对自己名称的管理员权限了注:RoleBinding仅仅对当前名称空间有对应的权限【4】用户基于clusterrolebinding绑定到clusterrole1.4、准入控制在k8s上准入控制器的模块有很多,其中比较常用的有:LimitRanger、ResourceQuota、ServiceAccount、PodSecurityPolicy(k8s 1.25已废弃)等等,对于前三种准入控制器系统默认是启用的,我们只需要定义对应的规则即可;对于PodSecurityPolicy(k8s1.25废弃了)这种准入控制器,系统默认没有启用,如果我们要使用,就必需启用以后,对应规则才会正常生效;这里需要注意一点,对应psp准入控制器,一定要先写好对应的规则,把规则和权限绑定好以后,在启用对应的准入控制器,否则先启用准入控制器,没有对应的规则,默认情况它是拒绝操作,这可能导致现有的k8s系统跑的系统级pod无法正常工作;所以对于psp准入控制器要慎用,如果规则和权限做的足够精细,它会给我们的k8s系统安全带来大幅度的提升,反之,可能导致整个k8s系统不可用。查看apiserver启用的准入控制器有哪些?[root@master ~]# cat /etc/kubernetes/manifests/kube-apiserver.yaml apiVersion: v1 kind: Pod metadata: annotations: kubeadm.kubernetes.io/kube-apiserver.advertise-address.endpoint: 10.32.1.147:6443 creationTimestamp: null labels: component: kube-apiserver tier: control-plane name: kube-apiserver namespace: kube-system spec: containers: - command: - kube-apiserver - --advertise-address=10.32.1.147 - --allow-privileged=true - --authorization-mode=Node,RBAC - --client-ca-file=/etc/kubernetes/pki/ca.crt - --enable-admission-plugins=NodeRestriction ......提示:apiserver启用准入控制插件需要使用–enable-admission-plugins选项来指定,该选项可以使用多个值,用逗号隔开表示启用指定的准入控制插件;这里配置文件中显式启用了NodeRestrication这个插件;默认没有写在这上面的内置准入控制器,它也是启用了的,比如LimitRanger、ResourceQuota、ServiceAccount等等;对于不同的k8s版本,内置的准入控制器和启用与否请查看相关版本的官方文档;对于那些没有启动的准入控制器,我们可以在上面选项中直接启用,分别用逗号隔开即可。对应的官网地址:https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/admission-controllers/二、k8s安全管理:账户2.1、Useraccount和ServiceAccount介绍kubernetes中账户分为:UserAccounts(用户账户) 和 ServiceAccounts(服务账户) 两种。【1】UserAccountUserAccount是给kubernetes集群外部用户使用的,如kubectl访问k8s集群要用useraccount用户, kubeadm安装的k8s,默认的useraccount用户是kubernetes-admin;APIServer需要对客户端做认证,使用kubeadm安装的K8s,会在用户家目录下创建一个认证配置文件 .kube/config 这里面保存了客户端访问API Server的密钥相关信息,这样当用kubectl访问k8s时,它就会自动读取该配置文件,向API Server发起认证,然后完成操作请求。用户名称可以在kubeconfig中查看[root@master ~]# cat ~/.kube/config ... users: - name: kubernetes-admin ...【2】ServiceAccountServiceAccount是Pod使用的账号,Pod容器的进程需要访问API Server时用的就是ServiceAccount账户;ServiceAccount仅局限它所在的namespace,每个namespace创建时都会自动创建一个default service account;创建Pod时,如果没有指定Service Account,Pod则会使用default Service Account。2.2、ServiceAccount使用案例介绍【1】创建sa,并绑定到pod[root@master 16]# kubectl create sa sa-test serviceaccount/sa-test created [root@master 16]# cat pod.yaml apiVersion: v1 kind: Pod metadata: name: sa-test namespace: default labels: app: sa spec: serviceAccountName: sa-test containers: - name: sa-tomcat ports: - containerPort: 80 image: nginx imagePullPolicy: IfNotPresent [root@master 16]# kubectl apply -f pod.yaml pod/sa-test created【2】运行pod进行,验证sa是否可以访问apiserver[root@master 16]# kubectl exec -it sa-test -- /bin/bash root@sa-test:/# cd /var/run/secrets/kubernetes.io/serviceaccount/ root@sa-test:/var/run/secrets/kubernetes.io/serviceaccount# curl --cacert ./ca.crt -H "Authorization: Bearer $(cat ./token)" https://kubernetes/api/v1/namespaces/kube-system { "kind": "Status", "apiVersion": "v1", "metadata": {}, "status": "Failure", "message": "namespaces \"kube-system\" is forbidden: User \"system:serviceaccount:default:sa-test\" cannot get resource \"namespaces\" in API group \"\" in the namespace \"kube-system\"", "reason": "Forbidden", "details": { "name": "kube-system", "kind": "namespaces" }, "code": 403 } # 上面结果能看到,sa能通过https方式成功认证API # 但是没有权限访问k8s资源,所以code状态码是403,表示没有权限操作k8s资源【3】对sa授权[root@master 16]# kubectl create clusterrolebinding sa-test-admin --clusterrole=cluster-admin --serviceaccount=default:sa-test clusterrolebinding.rbac.authorization.k8s.io/sa-test-admin created【4】再次请求# 请求指定ns空间下的资源 root@sa-tst:/var/run/secrets/kubernetes.io/serviceaccount# curl --cacert ./ca.crt -H "Authorization: Bearer $(cat ./token)" https://kubernetes/api/v1/namespaces/kube-system { "kind": "Namespace", "apiVersion": "v1", "metadata": { "name": "kube-system", "uid": "1634946c-f5c2-4b67-ad3a-425107a83cd0", "resourceVersion": "26", "creationTimestamp": "2023-12-06T02:47:03Z", "labels": { "kubernetes.io/metadata.name": "kube-system" }, "managedFields": [ { "manager": "kube-apiserver", "operation": "Update", "apiVersion": "v1", "time": "2023-12-06T02:47:03Z", "fieldsType": "FieldsV1", "fieldsV1": { "f:metadata": { "f:labels": { ".": {}, "f:kubernetes.io/metadata.name": {} } } } } ] }, "spec": { "finalizers": [ "kubernetes" ] }, "status": { "phase": "Active" } }root@sa-test:/var/run/secrets/kubernetes.io/serviceaccount# # 请求pod资源 root@sa-test:/var/run/secrets/kubernetes.io/serviceaccount# curl --cacert ./ca.crt -H "Authorization: Bearer $(cat ./token)" https://kubernetes/apiv1/pods ......三、RBAC认证授权策略RBAC介绍在Kubernetes中,所有资源对象都是通过API进行操作,他们保存在etcd里。而对etcd的操作我们需要通过访问 kube-apiserver 来实现,上面的Service Account其实就是APIServer的认证过程,而授权的机制是通过RBAC:基于角色的访问控制实现。3.1、Role角色一组权限的集合,在一个命名空间中,可以用其来定义一个角色,只能对命名空间内的资源进行授权。如果是集群级别的资源,则需要使用ClusterRole。例如:定义一个角色用来读取Pod的权限.apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: rbac name: pod-read rules: - apiGroups: [""] resources: ["pods"] resourceNames: [] verbs: ["get","watch","list"]rules中的参数说明:1、apiGroups:支持的API组列表,例如:"apiVersion: apps/v1"等2、resources:支持的资源对象列表,例如pods、deployments、jobs等3、resourceNames: 指定resource的名称4、verbs:对资源对象的操作方法列表。3.2、ClusterRole集群角色具有和角色一致的命名空间资源的管理能力,还可用于以下特殊元素的授权.1、集群范围的资源,例如Node2、非资源型的路径,例如:/healthz3、包含全部命名空间的资源,例如Pods例如:定义一个集群角色可让用户访问任意secretsapiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: secrets-clusterrole rules: - apiGroups: [""] resources: ["secrets"] verbs: ["get","watch","list"]3.3、RoleBinding角色绑定角色绑定和集群角色绑定用于把一个角色绑定在一个目标上,可以是User,Group,Service Account,使用RoleBinding为某个命名空间授权,使用ClusterRoleBinding为集群范围内授权。例如:将在rbac命名空间中把pod-read角色授予用户esapiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: pod-read-bind namespace: rbac subjects: - kind: User name: es apiGroup: rbac.authorization.k8s.io roleRef: - kind: Role name: pod-read apiGroup: rbac.authorizatioin.k8s.io3.4、ClusterRolebinding集群角色绑定RoleBinding也可以引用ClusterRole,对属于同一命名空间内的ClusterRole定义的资源主体进行授权.例如:es能获取到集群中所有的资源信息.apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: es-allresource namespace: rbac subjects: - kind: User name: es apiGroup: rbac.authorization.k8s.io roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin
0
0
0
浏览量2027
锅从天上来

K8S(五)—命名空间与资源配额

命名空间(Namespace)Kubernetes(K8s)的命名空间(Namespace)是用于在集群中对资源进行逻辑隔离和分类的一种机制。它可以将集群内的资源划分为不同的组,并且每个命名空间内的资源都有一个唯一的名称。命名空间可以帮助团队将不同的项目、环境或应用程序从彼此中隔离开来,以及更好地管理资源。以下是Kubernetes命名空间的详细介绍:1.隔离和资源分组: 命名空间允许将集群内的资源进行逻辑隔离和资源分组。每个命名空间内部的资源(例如Pod、Service、ReplicaSet等)都具有唯一的名称,但在不同的命名空间中可以有相同名称的资源。2.默认命名空间: 如果在创建资源时没有指定命名空间,则资源会被自动创建在名为"default"的命名空间中。因此,如果没有显式创建命名空间,大多数资源都位于"default"命名空间。3.多租户支持: 命名空间为多租户支持提供了基础。在同一个集群上,不同的团队、项目或用户可以使用不同的命名空间来管理和部署它们自己的资源,而不会相互干扰。4.访问控制: Kubernetes提供了基于RBAC(Role-Based Access Control)的访问控制机制。可以通过RBAC配置来限制用户或服务账号对特定命名空间中资源的访问权限。5.命名空间范围: 命名空间范围是指命名空间内的资源可以跨越的范围。例如,Cluster-wide资源(如节点和PersistentVolumes)不属于任何特定的命名空间,而Namespace-scoped资源(如Pod和Service)只属于一个命名空间。6.命名空间标签: 可以为命名空间添加标签(Labels),这些标签可以用于组织和筛选命名空间,以便更轻松地管理和查找资源。7.内置命名空间: Kubernetes提供了一些内置的命名空间,例如:   default: 默认命名空间,用于大多数资源的默认创建。   kube-system: 用于Kubernetes系统组件的命名空间,例如kube-dns、coredns、kube-proxy等。   kube-public: 这是一个特殊的命名空间,它对所有用户(包括未经身份验证的用户)都是可读的。一些集群信息和配置可以在这里公开。    kube-node-lease: 用于节点租约的命名空间,确保节点的健康状况。   kube-ingress: 用于Ingress控制器的命名空间。8.创建命名空间: 可以使用kubectl命令或YAML文件创建命名空间。例如:kubectl create namespace my-namespace9.指定命名空间: 在使用kubectl管理资源时,可以通过--namespace参数指定要操作的命名空间。例如:kubectl get pods --namespace=my-namespace命令查看所有的ns 命令:kubectl get nskubectl get namespace(ns)查看指定的ns 命令:kubectl get ns ns名称kubectl get ns default指定输出格式 命令:kubectl get ns ns名称 -o 格式参数kubernetes支持的格式有很多,比较常见的是wide、json、yaml [root@master ~]# kubectl get ns default -o yaml查看ns详情 命令:kubectl describe ns ns名称[root@master ~]# kubectl describe ns default计算资源配额资源配额,通过 ResourceQuota 对象来定义,对每个命名空间的资源消耗总量提供限制。 它可以限制命名空间中某种类型的对象的总数目上限,也可以限制命名空间中的 Pod 可以使用的计算资源的总上限。用户可以对给定命名空间下的可被请求的 计算资源 总量进行限制。配额机制所支持的资源类型:创建命名空间[root@k8smaster1 ~]# kubectl create namespace quota-mem-cpu-example绑定一个ResourceQuota资源[root@k8smaster ~]# cat quota-mem-cpu.yaml apiVersion: v1 kind: ResourceQuota metadata: name: mem-cpu-demo spec: hard: requests.cpu: "1" requests.memory: 1Gi limits.cpu: "2" limits.memory: 2Gi在该命名空间中的每个 Pod 的所有容器都必须要有内存请求和限制,以及 CPU 请求和限制。在该命名空间中所有 Pod 的内存请求总和不能超过 1 GiB。在该命名空间中所有 Pod 的内存限制总和不能超过 2 GiB。在该命名空间中所有 Pod 的 CPU 请求总和不能超过 1 cpu。在该命名空间中所有 Pod 的 CPU 限制总和不能超过 2 cpu。Requests(请求) 是容器在启动时向 Kubernetes 集群申请的资源(一开始)。它表明容器希望得到的最小资源量。如果容器实际使用的资源低于请求的量,Kubernetes 会为容器分配足够的资源。但是,如果容器实际使用的资源高于请求的量,Kubernetes 可能对容器进行 throttling,限制其使用的资源。Limits(限制) 是容器被允许使用的资源的上限(运行中)。它表明容器在运行时可以使用的资源的最大量。如果容器实际使用的资源超过了限制,Kubernetes 集群中的 QoS 机制可能会介入,可能导致容器被终止或限制其资源使用。所以,您的理解是正确的:请求是在容器启动时申请的资源量,而限制是在容器运行时允许使用的最大资源量。将命名空间和资源限制对象进行绑定[root@k8smaster1 ~]# kubectl apply -f quota-mem-cpu.yaml --namespace=quota-mem-cpu-example resourcequota/mem-cpu-demo created这是一个用于 Kubernetes 集群中的 kubectl 命令,用于将资源配额(ResourceQuota)配置文件应用到指定的命名空间。下面对命令及其参数进行详细解释:   kubectl apply:这是一个 kubectl 命令,用于将配置文件中定义的 Kubernetes 资源应用到集群。    -f quota-mem-cpu.yaml:这个参数指定了要应用的配置文件的路径。在这里,quota-mem-cpu.yaml 是一个 Kubernetes 配置文件的文件名,包含了定义资源配额的配置。   --namespace=quota-mem-cpu-example:这个参数用于指定要操作的命名空间(Namespace)。在这个命令中,您将资源配额应用到了 quota-mem-cpu-example 命名空间。综合起来,这个命令的作用是将位于 quota-mem-cpu.yaml 文件中定义的资源配额配置应用到了 quota-mem-cpu-example 命名空间中。资源配额可以用来限制在命名空间内可以使用的 CPU 和内存等资源的量,以确保资源在集群中的合理分配和控制。获取特定命名空间中的资源配额(ResourceQuota)的详细信息[root@k8smaster ~]# kubectl get resourcequota mem-cpu-demo --namespace=quota-mem-cpu-example --output=yaml这是一个使用 kubectl 命令的示例,用于获取特定命名空间中的资源配额(ResourceQuota)的详细信息,并以 YAML 格式进行输出。以下是命令及其参数的解析:    kubectl get resourcequota mem-cpu-demo:这部分命令用于获取资源配额对象。mem-cpu-demo 是要获取的资源配额的名称。    --namespace=quota-mem-cpu-example:这个参数指定了要操作的命名空间(Namespace),即 quota-mem-cpu-example。    --output=yaml:这个参数指定了输出格式。在这里,使用 yaml 格式进行输出,将资源配额的详细信息显示为 YAML 格式。综合起来,这个命令的作用是从 quota-mem-cpu-example 命名空间中获取名为 mem-cpu-demo 的资源配额的详细信息,并将其以 YAML 格式进行输出。通过执行该命令,您可以查看资源配额的配置和限制,以确保命名空间中的资源使用得到适当的控制和管理。尝试创建第二个 Pod新建quota-mem-cpu-pod.yaml[root@k8smaster1 ~]# cat quota-mem-cpu-pod.yaml apiVersion: v1 kind: Pod metadata: name: quota-mem-cpu-demo spec: containers: - name: quota-mem-cpu-demo-ctr image: nginx resources: limits: memory: "800Mi" cpu: "800m" requests: memory: "600Mi" cpu: "400m"绑定应用[root@k8smaster1 ~]# kubectl apply -f quota-mem-cpu-pod.yaml --namespace=quota-mem-cpu-example查看详细信息[root@k8smaster1 ~]# kubectl get pod -n quota-mem-cpu-example -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES quota-mem-cpu-demo 1/1 Running 0 101s 10.244.249.1 k8snode1 <none> <none>尝试创建第二个 Pod[root@k8smaster1 ~]# cat quota-mem-cpu-pod-2.yaml apiVersion: v1 kind: Pod metadata: name: quota-mem-cpu-demo-2 spec: containers: - name: quota-mem-cpu-demo-2-ctr image: redis resources: limits: memory: "1Gi" cpu: "800m" requests: memory: "700Mi" cpu: "400m" [root@k8smaster1 ~]# kubectl apply -f quota-mem-cpu-pod-2.yaml --namespace=quota-mem-cpu-example Error from server (Forbidden): error when creating "quota-mem-cpu-pod-2.yaml": pods "quota-mem-cpu-demo-2" is forbidden: exceeded quota: mem-cpu-demo, requested: requests.memory=700Mi, used: requests.memory=600Mi, limited: requests.memory=1Gi根据报错信息,运行命令 kubectl apply -f quota-mem-cpu-pod-2.yaml --namespace=quota-mem-cpu-example 时发生了错误。错误信息指出 Pod 的创建被拒绝,原因是超过了名为 “mem-cpu-demo” 的配额限制。让我们对错误信息进行解析:   Error from server: 从服务器返回的错误。    (Forbidden): 操作被拒绝。   error when creating "quota-mem-cpu-pod-2.yaml": 在创建 Pod 时出现了错误,具体是在处理 “quota-mem-cpu-pod-2.yaml” 文件时发生的问题。    pods "quota-mem-cpu-demo-2" is forbidden: 试图创建名为 “quota-mem-cpu-demo-2” 的 Pod 时被拒绝。    exceeded quota: mem-cpu-demo: 超过了 “mem-cpu-demo” 这个配额的限制。    requested: requests.memory=700Mi, used: requests.memory=600Mi, limited: requests.memory=1Gi: 在请求中指定了内存的配额,当前已经使用了 600Mi 内存,但是请求的配额超过了该配额的限制,所以 Pod 创建被拒绝了。解决这个问题的方法有两种:    1.调整 Pod 的资源配额: 在 “quota-mem-cpu-pod-2.yaml” 文件中调整 Pod 的资源配额,将请求的内存减少到 “1Gi” 以下,然后再次尝试运行 kubectl apply 命令。例如,将 requests.memory 的值设置为 “500M”。    2.调整配额限制: 修改名为 “mem-cpu-demo” 的配额限制,允许更高的内存请求。您可以使用 kubectl edit quota mem-cpu-demo --namespace=quota-mem-cpu-example 命令来编辑该配额,并增加 requests.memory 的限制值,然后保存退出。无论哪种方法,都需要确保请求的资源配额不超过配额限制,这样 Pod 才能够被成功创建。解决方法:选择将配额进行调整资源扩展后,第二个pod可以正常进去“quota-men-cpu-example”https://kubernetes.io/zh-cn/docs/concepts/policy/resource-quotas/查看ResourceQuota直接查询[root@k8smaster names]# kubectl get resourcequota mem-cpu-demo --namespace=quota-mem-cpu-example NAME AGE REQUEST LIMIT mem-cpu-demo 16h requests.cpu: 800m/2, requests.memory: 1300Mi/2Gi limits.cpu: 1600m/3, limits.memory: 1824Mi/3Gi查询以yaml文件进行输出kubectl get resourcequota mem-cpu-demo --namespace=quota-mem-cpu-example --output=yaml输出结果显示了配额以及有多少配额已经被使用。可以根据情况合理分配资源给pod中。下载 jq 工具,(使用 JSONPath) 直接查询 used 字段的值,并且输出整齐的 JSON 格式。centos/redhatsudo yum install jq -y查看命令。kubectl get resourcequota mem-cpu-demo --namespace=quota-mem-cpu-example -o jsonpath='{ .status.used }' | jq .查看“quota-mem-cpu-example”空间中的pod的资源消耗。[root@k8smaster names]# kubectl get pods --namespace=quota-mem-cpu-example -o=jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[0].resources.requests.cpu}{"\t"}{.spec.containers[0].resources.requests.memory}{"\n"}{end}' quota-mem-cpu-demo 400m 600Mi quota-mem-cpu-demo-2 400m 700Mi绑定第二个ResourceQuota编写第二个ResourceQuota文件apiVersion: v1 kind: ResourceQuota metadata: name: mem-cpu-demo-2 spec: hard: pods : "2" requests.cpu: "1" requests.memory: 1Gi limits.cpu: "2" limits.memory: 2Gi这里还进行了pod数量的限制。命名空间和资源绑定[root@k8smaster names]# kubectl apply -f quota-mem-cpu-2.yaml --namespace=quota-mem-cpu-example resourcequota/mem-cpu-demo-2 created可以看到一个命名空间中已经存在了多个ResourceQuota,在一个namespace创建多个resourcequota,他们共享内存,pod的创建能否进入这个命名空间,取决于该namespace中的多个ResourceQuota中的多个资源的request是否满足pod的申请数。为命名空间配置默认的 CPU 、memory请求和限制创建LimitRange的yaml文件,在该文件中的默认cpu、memory请求和默认cpu、memory限制。apiVersion: v1 kind: LimitRange metadata: name: cpu-limit-range spec: limits: - default: cpu: 1 memory: 1Gi defaultRequest: cpu: 0.5 memory: 500Mi type: Container和命名空间进行绑定[root@k8smaster names]# kubectl apply -f cpu-mem-defaults.yaml -n quota-mem-cpu-example limitrange/cpu-limit-range created查看详细信息kubectl describe limitrange -n quota-mem-cpu-example cpu-limit-range可以看到“quota-mem-cpu-example”命名空间中,本身存在一个ResourceQuota。这不影响,搭配使用效果更佳。如果只有ResourceQuota,里面设置了cpu、memory的请求和限制。    那么创建一个加入该命名空间的pod,需要有对应的cpu、memory请求和限制,否则会报错。    如何同时有一个ResourceQuota和一个LimitRange,现在不就pod中创建需要特定资源数可以,不指定资源数也可以了。同时ResourceQuota也做了一个命名空间的总资源的限制(1)Pod 中所有容器都没有声明自己的 CPU 请求和 CPU 限制创建容器的 Pod 的清单apiVersion: v1 kind: Pod metadata: name: default-cpu-demo spec: containers: - name: default-cpu-demo-ctr image: nginx创建podkubectl apply -f cpu-mem-pod.yaml -n quota-mem-cpu-example查看“cpu-mem-demo”的详细情况。kubectl get pod cpu-mem-demo --output=yaml -n quota-mem-cpu-example我们来看看ResourceQuota是什么情况,看看是不是cpu、memory也发生了相应的变化,是否能起到对该命名空间资源的整体把握。这是没有创建空资源pod的情况。这是创建后的情况可以发现ResourceQuota中的资源数也发生了相应的变化。(2)只声明容器的限制创建清单apiVersion: v1 kind: Pod metadata: name: cpu-mem-demo-2 spec: containers: - name: default-cpu-demo-2-ctr image: nginx resources: limits: cpu: "0.1"创建podkubectl apply -f cpu-mem-pod-2.yaml -n quota-mem-cpu-example查看“cpu-mem-demo”的详细情况。kubectl get pod cpu-mem-demo-2 --output=yaml -n quota-mem-cpu-example输出显示该容器的 CPU 请求和 CPU 限制设置相同。注意该容器没有被指定默认的 CPU 请求值 0.1 cpu:(3)只声明容器的请求声明pod清单apiVersion: v1 kind: Pod metadata: name: cpu-mem-demo-3 spec: containers: - name: default-cpu-demo-3-ctr image: nginx resources: requests: cpu: "0.2"创建pod[root@k8smaster names]# kubectl apply -f cpu-mem-pod-3.yaml -n quota-mem-cpu-examplepod申请的资源超过ResourceQuota限制,无法创建pod,这个时候可以选择缩减pod申请的系统资源,或者扩大ResourceQuota资源限制额。这里可以看到“memory”的申请和限制额都不足了,这里对pod资源申请进行缩减。[root@k8smaster names]# cat cpu-mem-pod-3.yaml apiVersion: v1 kind: Pod metadata: name: cpu-mem-demo-3 spec: containers: - name: default-cpu-demo-3-ctr image: nginx resources: requests: cpu: "0.2" memory: 100Mi limits: memory: 100Mi创建pod [root@k8smaster names]# kubectl apply -f cpu-mem-pod-3.yaml -n quota-mem-cpu-example pod/cpu-mem-demo-3 created输出显示所创建的 Pod 中,容器的 CPU 请求为 Pod 清单中声明的值。 然而同一容器的 CPU 限制被设置为 1 cpu,此值是该命名空间的默认 CPU 限制值。可以看到经过pod清单的调整,pod可以在“quota-mem-cpu-example”空间中被声明了。如果你的命名空间设置了 CPU 资源配额, 为 CPU 限制设置一个默认值会很有帮助。 以下是 CPU 资源配额对命名空间的施加的两条限制:       命名空间中运行的每个 Pod 中的容器都必须有 CPU 限制。        CPU 限制用来在 Pod 被调度到的节点上执行资源预留。预留给命名空间中所有 Pod 使用的 CPU 总量不能超过规定的限制。当你添加 LimitRange 时:如果该命名空间中的任何 Pod 的容器未指定 CPU 限制, 控制面将默认 CPU 限制应用于该容器, 这样 Pod 可以在受到 CPU ResourceQuota 限制的命名空间中运行。删除命名空间:kubectl delete namespace your-namespace当删除一个命名空间时,Kubernetes 会删除该命名空间中的所有资源,包括 Pod、Service、ConfigMap、Secret 等。这意味着在删除命名空间时,命名空间中的所有 Pod 也将被删除。limitrange 例子apiVersion: v1 kind: LimitRange metadata: name: example-limitrange spec: limits: - type: Container default: memory: "256Mi" cpu: "100m" max: memory: "512Mi" cpu: "200m" min: memory: "64Mi" cpu: "20m" 逐步解释这个配置文件:1.apiVersion: v1: 指定 Kubernetes API 的版本,这里是 v1。2.kind: LimitRange: 定义资源对象的类型,这里是 LimitRange。3.metadata: 包含对象的元数据,例如对象的名称。4.name: example-limitrange: 设置 LimitRange 对象的名称为 “example-limitrange”。5.spec: 指定 LimitRange 对象的规格,包括资源的限制。6.limits: 包含一个列表,其中定义了资源限制的规则。在这个例子中,只有一个规则,类型是 “Container”,表示这个规则适用于容器。7.max、min 和 default: 定义了对应资源(这里是内存和 CPU)的最大值、最小值和默认值。    对于内存(Memory):        最大值为 “512Mi”。        最小值为 “64Mi”。        默认值为 “256Mi”。    对于 CPU:        最大值为 “200m”(表示 200 毫核)。        最小值为 “20m”(表示 20 毫核)。        默认值为 “100m”(表示 100 毫核)。存储资源配额用户可以对给定命名空间下的存储资源 总量进行限制。此外,还可以根据相关的存储类(Storage Class)来限制存储资源的消耗。例如,如果一个操作人员针对 gold 存储类型与 bronze 存储类型设置配额, 操作人员可以定义如下配额:gold.storageclass.storage.k8s.io/requests.storage: 500Gibronze.storageclass.storage.k8s.io/requests.storage: 100Gi在 Kubernetes 1.8 版本中,本地临时存储的配额支持已经是 Alpha 功能:说明:如果所使用的是 CRI 容器运行时,容器日志会被计入临时存储配额。 这可能会导致存储配额耗尽的 Pods 被意外地驱逐出节点。 参考日志架构 了解详细信息。示例创建命名空间(storage)[root@k8smaster names]# kubectl create ns storage namespace/storage created当设置存储资源配额时,可以根据具体的需求和实际情况进行调整。以下是更多详细的存储资源配额的例子:apiVersion: v1 kind: ResourceQuota metadata: name: storage-quota spec: hard: # 设置存储请求的总和不超过10Gi requests.storage: "10Gi" # 设置CPU限制总和不超过4核 limits.cpu: "4" # 设置内存限制总和不超过8Gi limits.memory: "8Gi" # 设置PersistentVolume数量不超过3个 persistentvolumeclaims: "3" # 设置Service数量不超过5个 services: "5" # 设置ConfigMap和Secret的总和不超过10个 configmaps: "5" secrets: "5" 在这个例子中,配额限制了命名空间中的存储资源使用情况:存储请求总和不能超过10 GiB。CPU限制总和不能超过4核。内存限制总和不能超过8 GiB。PersistentVolume数量不能超过3个。Service数量不能超过5个。ConfigMap和Secret的总和不能超过10个。ResourceQuota和命名空间绑定。[root@k8smaster names]# kubectl apply -f storage.yaml -n storage resourcequota/storage-quota created查看ResourceQuota详细信息[root@k8smaster names]# kubectl get resourcequota -n storage NAME AGE REQUEST LIMIT storage-quota 98s configmaps: 1/5, persistentvolumeclaims: 0/3, requests.storage: 0/10Gi, secrets: 1/5, services: 0/5 limits.cpu: 0/4, limits.memory: 0/8Gi对象数量配额你可以使用以下语法对所有标准的、命名空间域的资源类型进行配额设置:count/<resource>.<group>:用于非核心(core)组的资源count/<resource>:用于核心组的资源这是用户可能希望利用对象计数配额来管理的一组资源示例。count/persistentvolumeclaimscount/servicescount/secretscount/configmapscount/replicationcontrollerscount/deployments.appscount/replicasets.appscount/statefulsets.appscount/jobs.batchcount/cronjobs.batch相同语法也可用于自定义资源。 例如,要对 example.com API 组中的自定义资源 widgets 设置配额,请使用 count/widgets.example.com。当使用 count/* 资源配额时,如果对象存在于服务器存储中,则会根据配额管理资源。 这些类型的配额有助于防止存储资源耗尽。例如,用户可能想根据服务器的存储能力来对服务器中 Secret 的数量进行配额限制。 集群中存在过多的 Secret 实际上会导致服务器和控制器无法启动。 用户可以选择对 Job 进行配额管理,以防止配置不当的 CronJob 在某命名空间中创建太多 Job 而导致集群拒绝服务。对有限的一组资源上实施一般性的对象数量配额也是可能的。支持以下类型:例如,pods 配额统计某个命名空间中所创建的、非终止状态的 Pod 个数并确保其不超过某上限值。 用户可能希望在某命名空间中设置 pods 配额,以避免有用户创建很多小的 Pod, 从而耗尽集群所能提供的 Pod IP 地址。示例创建命名空间(storage)[root@k8smaster names]# kubectl create ns object namespace/object created以下是一组可于管理的资源类型的对象计数配额的示例:yamlCopy codeapiVersion: v1 kind: ResourceQuota metadata: name: example-object-quota spec: hard: count/persistentvolumeclaims: 5 count/services: 10 count/secrets: 20 count/configmaps: 15 count/replicationcontrollers: 3 count/deployments.apps: 2 count/replicasets.apps: 4 count/statefulsets.apps: 1 count/jobs.batch: 5 count/cronjobs.batch: 2与命名空间进行绑定。配额作用域每个配额都有一组相关的 scope(作用域),配额只会对作用域内的资源生效。 配额机制仅统计所列举的作用域的交集中的资源用量。当一个作用域被添加到配额中后,它会对作用域相关的资源数量作限制。 如配额中指定了允许(作用域)集合之外的资源,会导致验证错误。BestEffort 作用域限制配额跟踪以下资源:podsTerminating、NotTerminating、NotBestEffort 和 PriorityClass 这些作用域限制配额跟踪以下资源:podscpumemoryrequests.cpurequests.memorylimits.cpulimits.memory需要注意的是,你不可以在同一个配额对象中同时设置 Terminating 和 NotTerminating 作用域,你也不可以在同一个配额中同时设置 BestEffort 和 NotBestEffort 作用域。scopeSelector 支持在 operator 字段中使用以下值:InNotInExistsDoesNotExist定义 scopeSelector 时,如果使用以下值之一作为 scopeName 的值,则对应的 operator 只能是 Exists。TerminatingNotTerminatingBestEffortNotBestEffort如果 operator 是 In 或 NotIn 之一,则 values 字段必须至少包含一个值。 例如: scopeSelector: matchExpressions: - scopeName: PriorityClass operator: In values: - middle如果 operator 为 Exists 或 DoesNotExist,则不可以设置 values 字段。示例一个配额对象中使用不同的作用域进行资源数量限制:apiVersion: v1 kind: ResourceQuota metadata: name: example-resource-quota spec: hard: pods: "10" cpu: "2" memory: 2Gi requests.cpu: "1" requests.memory: 1Gi limits.cpu: "1.5" limits.memory: 1.5Gi scopeSelector: matchScopes: - Terminating - NotBestEffort - PriorityClass - CrossNamespacePodAffinity operator: In values: - middle在这个例子中:hard 字段定义了资源的硬性限制,包括 Pod 数量、CPU 使用、内存使用,以及请求和限制的 CPU 和内存。scopeSelector 字段定义了作用域选择器,包括 Terminating、NotBestEffort、PriorityClass 和 CrossNamespacePodAffinity。它使用 In 操作符,表示这些作用域的交集中的资源会受到限制。对于 PriorityClass,配额限制了引用了 “middle” 优先级类的 Pods。请注意,这只是一个示例,实际中你需要根据你的需求来调整这些作用域和配额值。基于优先级类(PriorityClass)来设置资源配额特性状态: Kubernetes v1.17 [stable]Pod 可以创建为特定的优先级。 通过使用配额规约中的 scopeSelector 字段,用户可以根据 Pod 的优先级控制其系统资源消耗。仅当配额规范中的 scopeSelector 字段选择到某 Pod 时,配额机制才会匹配和计量 Pod 的资源消耗。如果配额对象通过 scopeSelector 字段设置其作用域为优先级类, 则配额对象只能跟踪以下资源:podscpumemoryephemeral-storagelimits.cpulimits.memorylimits.ephemeral-storagerequests.cpurequests.memoryrequests.ephemeral-storage本示例创建一个配额对象,并将其与具有特定优先级的 Pod 进行匹配。 该示例的工作方式如下:集群中的 Pod 可取三个优先级类之一,即 “low”、“medium”、“high”。为每个优先级创建一个配额对象。将以下 YAML 保存到文件 quota.yml 中。apiVersion: v1 kind: List items: - apiVersion: v1 kind: ResourceQuota metadata: name: pods-high spec: hard: cpu: "500" memory: 5Gi pods: "10" scopeSelector: matchExpressions: - operator: In scopeName: PriorityClass values: ["high"] - apiVersion: v1 kind: ResourceQuota metadata: name: pods-medium spec: hard: cpu: "100" memory: 2Gi pods: "10" scopeSelector: matchExpressions: - operator: In scopeName: PriorityClass values: ["medium"] - apiVersion: v1 kind: ResourceQuota metadata: name: pods-low spec: hard: cpu: "10" memory: 1Gi pods: "10" scopeSelector: matchExpressions: - operator: In scopeName: PriorityClass values: ["low"]使用 kubectl create 命令运行以下操作。kubectl create -f ./quota.yml resourcequota/pods-high created resourcequota/pods-medium created resourcequota/pods-low created使用 kubectl describe quota 操作验证配额的 Used 值为 0。kubectl describe quota Name: pods-high Namespace: default Resource Used Hard -------- ---- ---- cpu 0 500 memory 0 5Gi pods 0 10 Name: pods-low Namespace: default Resource Used Hard -------- ---- ---- cpu 0 10 memory 0 1Gi pods 0 10 Name: pods-medium Namespace: default Resource Used Hard -------- ---- ---- cpu 0 100 memory 0 2Gi pods 0 10 创建优先级为 “high” 的 Pod。 将以下 YAML 保存到文件 high-priority-pod.yml 中。apiVersion: v1 kind: Pod metadata: name: high-priority spec: containers: - name: high-priority image: ubuntu command: ["/bin/sh"] args: ["-c", "while true; do echo hello; sleep 10;done"] resources: requests: memory: "2Gi" cpu: "100m" limits: memory: "3Gi" cpu: "150m" priorityClassName: high创建一个名为“high”的prorityclass的yaml文件apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: high value: 1000000 # 根据您的优先级要求调整值 globalDefault: false description: "此 PriorityClass 用于高优先级 Pods。"进行声明kubectl apply -f high-priority-class.yaml查看“priorityclass”[root@k8smaster priority]# kubectl get priorityclass NAME VALUE GLOBAL-DEFAULT AGE high 1000000 false 3m10s system-cluster-critical 2000000000 false 27d system-node-critical 2000001000 false 27d 使用 kubectl create 运行以下操作。kubectl create -f ./high-priority-pod.yml确认 “high” 优先级配额 pods-high 的 “Used” 统计信息已更改,并且其他两个配额未更改。kubectl describe quota Name: pods-high Namespace: default Resource Used Hard -------- ---- ---- cpu 100m 500 memory 2Gi 5Gi pods 1 10 Name: pods-low Namespace: default Resource Used Hard -------- ---- ---- cpu 0 10 memory 0 1Gi pods 0 10 Name: pods-medium Namespace: default Resource Used Hard -------- ---- ---- cpu 0 100 memory 0 2Gi pods 0 10跨名字空间的 Pod 亲和性配额特性状态: Kubernetes v1.24 [stable]集群运维人员可以使用 CrossNamespacePodAffinity 配额作用域来限制哪个名字空间中可以存在包含跨名字空间亲和性规则的 Pod。 更为具体一点,此作用域用来配置哪些 Pod 可以在其 Pod 亲和性规则中设置 namespaces 或 namespaceSelector 字段。禁止用户使用跨名字空间的亲和性规则可能是一种被需要的能力, 因为带有反亲和性约束的 Pod 可能会阻止所有其他名字空间的 Pod 被调度到某失效域中。使用此作用域操作符可以避免某些名字空间(例如下面例子中的 foo-ns)运行特别的 Pod, 这类 Pod 使用跨名字空间的 Pod 亲和性约束,在该名字空间中创建了作用域为 CrossNamespacePodAffinity 的、硬性约束为 0 的资源配额对象。apiVersion: v1 kind: ResourceQuota metadata: name: disable-cross-namespace-affinity namespace: foo-ns spec: hard: pods: "0" scopeSelector: matchExpressions: - scopeName: CrossNamespacePodAffinity operator: Exists如果集群运维人员希望默认禁止使用 namespaces 和 namespaceSelector, 而仅仅允许在特定名字空间中这样做,他们可以将 CrossNamespacePodAffinity 作为一个被约束的资源。方法是为 kube-apiserver 设置标志 --admission-control-config-file,使之指向如下的配置文件:apiVersion: apiserver.config.k8s.io/v1 kind: AdmissionConfiguration plugins: - name: "ResourceQuota" configuration: apiVersion: apiserver.config.k8s.io/v1 kind: ResourceQuotaConfiguration limitedResources: - resource: pods matchScopes: - scopeName: CrossNamespacePodAffinity operator: Exists基于上面的配置,只有名字空间中包含作用域为 CrossNamespacePodAffinity 且硬性约束大于或等于使用 namespaces 和 namespaceSelector 字段的 Pod 个数时,才可以在该名字空间中继续创建在其 Pod 亲和性规则中设置 namespaces 或 namespaceSelector 的新 Pod。请求与限制的比较分配计算资源时,每个容器可以为 CPU 或内存指定请求和约束。 配额可以针对二者之一进行设置。如果配额中指定了 requests.cpu 或 requests.memory 的值,则它要求每个容器都显式给出对这些资源的请求。 同理,如果配额中指定了 limits.cpu 或 limits.memory 的值,那么它要求每个容器都显式设定对应资源的限制。查看和设置配额Kubectl 支持创建、更新和查看配额:kubectl create namespace myspace cat <<EOF > compute-resources.yaml apiVersion: v1 kind: ResourceQuota metadata: name: compute-resources spec: hard: requests.cpu: "1" requests.memory: 1Gi limits.cpu: "2" limits.memory: 2Gi requests.nvidia.com/gpu: 4 EOF kubectl create -f ./compute-resources.yaml --namespace=myspace cat <<EOF > object-counts.yaml apiVersion: v1 kind: ResourceQuota metadata: name: object-counts spec: hard: configmaps: "10" persistentvolumeclaims: "4" pods: "4" replicationcontrollers: "20" secrets: "10" services: "10" services.loadbalancers: "2" EOF kubectl create -f ./object-counts.yaml --namespace=myspace kubectl get quota --namespace=myspace NAME AGE compute-resources 30s object-counts 32s kubectl describe quota compute-resources --namespace=myspace Name: compute-resources Namespace: myspace Resource Used Hard -------- ---- ---- limits.cpu 0 2 limits.memory 0 2Gi requests.cpu 0 1 requests.memory 0 1Gi requests.nvidia.com/gpu 0 4 kubectl describe quota object-counts --namespace=myspace pace Name: object-counts Namespace: myspace Resource Used Hard -------- ---- ---- configmaps 1 10 persistentvolumeclaims 0 4 pods 0 4 replicationcontrollers 0 20 secrets 1 10 services 0 10 services.loadbalancers 0 2查看“configmaps”[root@k8smaster priority]# kubectl get configmaps --namespace=myspace NAME DATA AGE kube-root-ca.crt 1 79s kubectl describe configmap kube-root-ca.crt --namesp ace=myspace ace=myspace Name: kube-root-ca.crt Namespace: myspace Labels: <none> Annotations: <none> Data ==== ca.crt: ---- -----BEGIN CERTIFICATE----- MIIC5zCCAc+gAwIBAgIBADANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwprdWJl cm5ldGVzMB4XDTIzMTEwMTA2MjkzMVoXDTMzMTAyOTA2MjkzMVowFTETMBEGA1UE AxMKa3ViZXJuZXRlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM4/ LpHETK0oO//kLbYIBao8XkpOlngeCI9LDjPb3EZ0RHJvfPLSf76+hnDTfnQng4W8 xWqKKD7TMgyQQxRXRmkf5fr6hzYK+PfCnNnw7JxlXv1s/Ne5Fwq3xWSzpbR1UrUz j4UeYHGFcEbmkLk8574Okte0fEIXJ7xalavSUQPIVlCN+pmBYMk1emhpzjCaQfKY 9p41r43ADAiHeLNqpeJsS3Cypgc1ra7i+hLGRQ0x18lJ5a4ri2x42gMl4JWUkrZz j0xV4BvtF7apl9FBclIutbUQA5j6eFu+9a5k6J9XquhtwpjIfVxl2x18WblH+ogy /AeLdvSyo2A6XIS7rDsCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgKkMA8GA1UdEwEB /wQFMAMBAf8wHQYDVR0OBBYEFGvglNTMLDATLYCDVj1xHuLdLKDgMA0GCSqGSIb3 DQEBCwUAA4IBAQBT1sQR3E6mumre6b18YmxNeFXXMgY21fOthS9S6zT/6of6qKBZ 5LXsQAmFQeaDlqTTWb5EgHzr1P9Ew0Y2A303Uoyb/H3qosjvgEOnwUlj/zL5mx+l 3i3v/ZTflGRKnLhNFVVmB2QOPlaTp0haE8bbPv1QyEJydQOkOCLDxJCeHtZawWrI 2DXaq+CBdUz2RKOOr8o53mhYeLuaF7vQcv8V2s+EPnbzeRUWXqdTaMsLv4GOlIVC kKXM+P37T4ASrC/M6lpWukraE6UnFF5O+iw0Xv9YTE4UcbV41BMmgHsMfbdz87E3 c6ztPxXaAe9maDTZ6wBBVeoShr+oqmyFGwVQ -----END CERTIFICATE----- Events: <none> kubectl 还使用语法 count/<resource>.<group> 支持所有标准的、命名空间域的资源的对象计数配额:kubectl create namespace myspace kubectl create quota test --hard=count/deployments.apps=2,count/replicasets.apps=4,count/pods=3,count/secrets=4 --namespace=myspace kubectl create deployment nginx --image=nginx --namespace=myspace --replicas=2 kubectl describe quota --namespace=myspace Name: test Namespace: myspace Resource Used Hard -------- ---- ---- count/deployments.apps 1 2 count/pods 2 3 count/replicasets.apps 1 4 count/secrets 1 4配额和集群容量ResourceQuota 与集群资源总量是完全独立的。它们通过绝对的单位来配置。 所以,为集群添加节点时,资源配额不会自动赋予每个命名空间消耗更多资源的能力。有时可能需要资源配额支持更复杂的策略,比如:在几个团队中按比例划分总的集群资源。允许每个租户根据需要增加资源使用量,但要有足够的限制以防止资源意外耗尽。探测某个命名空间的需求,添加物理节点并扩大资源配额值。这些策略可以通过将资源配额作为一个组成模块、手动编写一个控制器来监控资源使用情况, 并结合其他信号调整命名空间上的硬性资源配额来实现。注意:资源配额对集群资源总体进行划分,但它对节点没有限制:来自不同命名空间的 Pod 可能在同一节点上运行。默认情况下限制特定优先级的资源消耗有时候可能希望当且仅当某名字空间中存在匹配的配额对象时,才可以创建特定优先级 (例如 “cluster-services”)的 Pod。通过这种机制,操作人员能够限制某些高优先级类仅出现在有限数量的命名空间中, 而并非每个命名空间默认情况下都能够使用这些优先级类。要实现此目的,应设置 kube-apiserver 的标志 --admission-control-config-file 指向如下配置文件:apiVersion: apiserver.config.k8s.io/v1 kind: AdmissionConfiguration plugins: - name: "ResourceQuota" configuration: apiVersion: apiserver.config.k8s.io/v1 kind: ResourceQuotaConfiguration limitedResources: - resource: pods matchScopes: - scopeName: PriorityClass operator: In values: ["cluster-services"]现在在 kube-system 名字空间中创建一个资源配额对象:policy/priority-class-resourcequota.yamlapiVersion: v1 kind: ResourceQuota metadata: name: pods-cluster-services spec: scopeSelector: matchExpressions: - operator : In scopeName: PriorityClass values: ["cluster-services"] kubectl apply -f https://k8s.io/examples/policy/priority-class-resourcequota.yaml -n kube-system resourcequota/pods-cluster-services created在这里,当以下条件满足时可以创建 Pod:1.Pod 未设置 priorityClassName2.Pod 的 priorityClassName 设置值不是 cluster-services3.Pod 的 priorityClassName 设置值为 cluster-services,它将被创建于 kube-system 名字空间中,并且它已经通过了资源配额检查。如果 Pod 的 priorityClassName 设置为 cluster-services,但要被创建到 kube-system 之外的别的名字空间,则 Pod 创建请求也被拒绝。
0
0
0
浏览量2009
锅从天上来

K8S(二)—介绍

K8S的整体结构图k8s对象在 Kubernetes 系统中,Kubernetes 对象是持久化的实体。 Kubernetes 使用这些实体去表示整个集群的状态。 具体而言,它们描述了如下信息:哪些容器化应用正在运行(以及在哪些节点上运行)可以被应用使用的资源关于应用运行时行为的策略,比如重启策略、升级策略以及容错策略Kubernetes 对象是一种“意向表达(Record of Intent)”。一旦创建该对象, Kubernetes 系统将不断工作以确保该对象存在。通过创建对象,你本质上是在告知Kubernetes 系统,你想要的集群工作负载状态看起来应是什么样子的, 这就是 Kubernetes 集群所谓的期望状态(Desired State)。操作 Kubernetes 对象 —— 无论是创建、修改或者删除 —— 需要使用 Kubernetes API。 比如,当使用 kubectl 命令行接口(CLI)时,CLI 会调用必要的 Kubernetes API; 也可以在程序中使用客户端库, 来直接调用 Kubernetes API。对象规约(Spec)与状态(Status)几乎每个 Kubernetes 对象包含两个嵌套的对象字段,它们负责管理对象的配置: 对象 spec(规约) 和对象 status(状态)。 对于具有 spec 的对象,你必须在创建对象时设置其内容,描述你希望对象所具有的特征: 期望状态(Desired State)。status 描述了对象的当前状态(Current State),它是由 Kubernetes 系统和组件设置并更新的。在任何时刻,Kubernetes 控制平面 都一直在积极地管理着对象的实际状态,以使之达成期望状态。例如,Kubernetes 中的 Deployment 对象能够表示运行在集群中的应用。 当创建 Deployment 时,你可能会设置 Deployment 的 spec,指定该应用要有 3 个副本运行。 Kubernetes 系统读取 Deployment 的 spec, 并启动我们所期望的应用的 3 个实例 —— 更新状态以与规约相匹配。 如果这些实例中有的失败了(一种状态变更),Kubernetes 系统会通过执行修正操作来响应 spec 和 status 间的不一致 —— 意味着它会启动一个新的实例来替换。描述 Kubernetes 对象创建 Kubernetes 对象时,必须提供对象的 spec,用来描述该对象的期望状态, 以及关于对象的一些基本信息(例如名称)。 当使用 Kubernetes API 创建对象时(直接创建或经由 kubectl 创建), API 请求必须在请求主体中包含 JSON 格式的信息。 大多数情况下,你需要提供 .yaml 文件为 kubectl 提供这些信息。 kubectl 在发起 API 请求时,将这些信息转换成 JSON 格式。这里有一个 .yaml 示例文件,展示了 Kubernetes Deployment 的必需字段和对象 spec:apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: selector: matchLabels: app: nginx replicas: 2 # 告知 Deployment 运行 2 个与该模板匹配的 Pod template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80这是一个用于创建Deployment对象的Kubernetes配置文件。让我们逐个字段进行解析:1.apiVersion: apps/v1:这是指定使用的Kubernetes API版本。在这个配置中,使用了apps/v1版本,表示我们将使用apps API组中的v1版本来创建Deployment对象。2.kind: Deployment:这定义了要创建的Kubernetes对象的类型,这里是一个Deployment对象。3.metadata:这是Deployment对象的元数据部分,用于定义对象的名称等信息。name: nginx-deployment:这是Deployment对象的名称,被设置为"nginx-deployment"。4.spec:这是Deployment对象的规约部分,描述了期望的状态和配置。selector:该字段用于标记将由Deployment控制的Pod。在这里,使用matchLabels来选择拥有标签"app: nginx"的Pod。replicas: 2:这指定Deployment所需的Pod副本数为2个。Deployment会确保集群中始终有两个与该模板匹配的Pod在运行,如果Pod数少于2,它会自动创建新的Pod以达到所需的数量。template:这是Pod模板,描述了要创建的Pod的配置。     metadata:     这里是Pod的元数据部分。            labels:            这里定义了Pod的标签,标签"app: nginx"与上面的selector匹配,使得Deployment能够控制这些Pod。     spec:     这是Pod的规约部分,描述了Pod的具体配置。           containers:            这是Pod中的容器部分。                    name: nginx:                    容器的名称被设置为"nginx"。                    image: nginx:1.14.2:                    这是要使用的nginx镜像及其版本。                    ports:                    这里定义了容器的端口配置。                            containerPort: 80:                                    容器将监听80端口,使得能够通过该端口访问nginx服务。以上配置文件描述了一个名为"nginx-deployment"的Deployment对象,它控制运行两个nginx容器副本,并通过标签"app: nginx"来选择这些Pod。每个Pod都包含一个名为"nginx"的容器,使用nginx:1.14.2镜像,并在容器内监听80端口。相较于上面使用 .yaml 文件来创建 Deployment,另一种类似的方式是使用 kubectl 命令行接口(CLI)中的 kubectl apply 命令, 将 .yaml 文件作为参数。下面是一个示例:kubectl apply -f https://k8s.io/examples/application/deployment.yaml输出类似下面这样:deployment.apps/nginx-deployment created必需字段在想要创建的 Kubernetes 对象所对应的 .yaml 文件中,需要配置的字段如下:apiVersion - 创建该对象所使用的 Kubernetes API 的版本kind - 想要创建的对象的类别metadata - 帮助唯一标识对象的一些数据,包括一个 name 字符串、UID 和可选的 namespacespec - 你所期望的该对象的状态对每个 Kubernetes 对象而言,其 spec 之精确格式都是不同的,包含了特定于该对象的嵌套字段。 Kubernetes API 参考可以帮助你找到想要使用 Kubernetes 创建的所有对象的规约格式。例如,参阅 Pod API 参考文档中 spec 字段。 对于每个 Pod,其 .spec 字段设置了 Pod 及其期望状态(例如 Pod 中每个容器的容器镜像名称)。 另一个对象规约的例子是 StatefulSet API 中的 spec 字段。 对于 StatefulSet 而言,其 .spec 字段设置了 StatefulSet 及其期望状态。 在 StatefulSet 的 .spec 内,有一个为 Pod 对象提供的模板。 该模板描述了 StatefulSet 控制器为了满足 StatefulSet 规约而要创建的 Pod。 不同类型的对象可以有不同的 .status 信息。API 参考页面给出了 .status 字段的详细结构, 以及针对不同类型 API 对象的具体内容。label(标签)在Kubernetes(K8s)中,label是用来附着到资源对象(如Pod、Node、Service等)上的键值对。它是一种元数据,允许您对资源进行更灵活的组织、查询和选择。下面是一些关于Kubernetes中label的详细解释:什么是Label:•Label是键值对(key-value pair)的元数据,附着在Kubernetes资源对象上。•Label不是唯一标识符,多个资源可以共享相同的label。Label的作用:•组织和选择: Labels可以用来组织和选择资源对象。您可以使用label选择器(label selectors)来筛选出具有特定label的资源。•路由和调度: Labels可以用于定义服务的路由规则,也可用于调度Pod到特定的Node。Label的语法:•Label的键和值都是字符串。•label键可以包含斜杠(/),但是一些工具可能不支持这种形式。Label的附着:•Label可以在资源创建时附着,也可以在后期修改。•使用kubectl命令行工具或Kubernetes API可以对资源添加或删除label。Label选择器:•Label选择器是一种通过label对资源进行查询的机制。•通过使用kubectl或在Pod定义中指定nodeSelector字段,您可以选择特定label的Pod或Node。使用Label的例子:•Pod调度: 使用Node的label和Pod的nodeSelector字段,可以实现将Pod调度到具有特定属性的Node上。•服务路由: 使用Service的label和Ingress Controller,可以实现基于label的服务路由。下面是一个Pod定义的示例,其中使用了label和nodeSelector字段:apiVersion: v1 kind: Pod metadata: name: mypod labels: app: myapp tier: frontend spec: containers: - name: mycontainer image: nginx nodeSelector: size: Large在这个例子中,Pod有两个label:app: myapp和tier: frontend。它还通过nodeSelector字段指定,只能调度到拥有label size: Large 的Node上。总体来说,Kubernetes中的label是一项非常有用的功能,使得资源的组织、查询和选择变得更加灵活。nodeSelector在 Kubernetes 中,nodeSelector 是一种用于将 Pod 调度到特定节点的机制。通过 nodeSelector,你可以根据节点上的标签进行选择,以确保 Pod 被调度到符合条件的节点上。以下是 nodeSelector 的详解:1.基本语法: nodeSelector 被定义在 Pod 的规范(spec)中,它是一个键值对的映射,其中键是节点标签的键,值是节点标签的值。nodeSelector: key: value2.示例: 假设你的节点上有一个标签 size,你可以使用 nodeSelector 将 Pod 调度到具有特定 size 值的节点上。nodeSelector: size: Large上述配置表示 Pod 将只会被调度到具有标签 size=Large 的节点上。3.多个条件: 你可以使用多个键值对来定义多个条件,这样 Pod 将仅在节点满足所有条件时被调度。nodeSelector: size: Large environment: production上述配置表示 Pod 将只会被调度到同时具有标签 size=Large 和 environment=production 的节点上。4.查看所有节点及其标签:这个命令将列出所有节点以及它们的标签kubectl get nodes --show-labels5.查看特定节点的标签:kubectl get node <node-name> --show-labels6.节点选择器和标签的设置: 在将 Pod 调度到节点上之前,确保节点上已经设置了相应的标签。你可以使用 kubectl label nodes <node-name> <label-key>=<label-value> 命令为节点设置标签。kubectl label nodes node-1 size=Large7.删除标签:kubectl label nodes k8snode1 size-8.更改标签值:kubectl label nodes k8snode1 size=Large --overwrite如果更改 size 这个标签的值,可以使用 kubectl label 命令,并指定 --overwrite=true 参数9.存在性检查: 你还可以使用 exists 来检查节点是否具有某个标签。nodeSelector: size: Exists上述配置表示 Pod 将只会被调度到具有任何 size 标签的节点上。nodeSelector 提供了一种简单而有效的方式,通过标签条件将 Pod 调度到特定节点。这对于在节点上部署特定类型的工作负载或应用程序非常有用。
0
0
0
浏览量2014
锅从天上来

【Kubernetes】控制器Statefulset

一、概念StatefulSet是为了管理有状态服务的问题而设计的.扩展:有状态服务?StatefulSet是有状态的集合,管理有状态的服务,它所管理的Pod的名称不能随意变化。数据持久化的目录也是不一样,每一个Pod都有自己独有的数据持久化存储目录。比如MySQL主从、redis集群等。无状态服务?RC、Deployment、DaemonSet都是管理无状态的服务,它们所管理的Pod的IP、名字,启停顺序等都是随机的。个体对整体无影响,所有pod都是共用一个数据卷的,部署的tomcat就是无状态的服务,tomcat被删除,在启动一个新的tomcat,加入到集群即可,跟tomcat的名字无关。二、Statefulset资源清单文件编写技巧2.1、查看定义Statefulset资源需要的字段[root@master ~]# kubectl explain statefulset KIND: StatefulSet VERSION: apps/v1 DESCRIPTION: StatefulSet represents a set of pods with consistent identities. Identities are defined as: - Network: A single stable DNS and hostname. - Storage: As many VolumeClaims as requested. The StatefulSet guarantees that a given network identity will always map to the same storage identity. FIELDS: apiVersion <string> # 定义资源需要使用的api版本 kind <string> # 定义资源类型 metadata <Object> # 定义元数据 spec <Object> # 定义容器相关的信息 2.2、查看statefulset.spec字段如何定义[root@master ~]# kubectl explain statefulset.spec KIND: StatefulSet VERSION: apps/v1 RESOURCE: spec <Object> DESCRIPTION: Spec defines the desired identities of pods in this set. A StatefulSetSpec is the specification of a StatefulSet. FIELDS: podManagementPolicy <string> # POD管理策略 replicas <integer> # 副本数 revisionHistoryLimit <integer> # 保留的历史版本 selector <Object> -required- # 标签选择器,选择它所关联的pod serviceName <string> -required- # headless service的名字 template <Object> -required- # 生成pod的模板 updateStrategy <Object> # 更新策略 volumeClaimTemplates <[]Object> # 存储卷申请模板2.3、查看statefulset的spec.template字段如何定义对于template而言,其内部定义的就是pod,pod模板是一个独立的对象。.spec.template里的内容是声明Pod对象时要定义的各种属性,所以这部分也叫做PodTemplate(Pod模板)[root@master ~]# kubectl explain statefulset.spec.template KIND: StatefulSet VERSION: apps/v1 RESOURCE: template <Object> DESCRIPTION: ...... FIELDS: metadata <Object> # 定义多少个Pod副本(默认将仅部署1个Pod)、匹配Pod标签的选择器、创建pod的模板、存储卷申请模板 spec <Object> # Pod里的容器属性等配置 # 在spec.template.spec.selector中定义的标签选择器必须能够匹配到spec.template.metadata.labels里定义的Pod标签,否则Kubernetes将不允许创建statefulset。三、Statefulset使用案例:部署web站点3.1、编写一个Statefulset资源清单文件[root@master 12]# cat statefulset.yaml apiVersion: v1 # 定义api版本 kind: Service # 定义要创建的资源:service metadata: name: nginx # 定义service的名字 labels: app: nginx # service的标签 spec: ports: - port: 80 name: web clusterIP: None # 创建一个没有ip的service selector: app: nginx # 选择拥有app=nginx标签的pod --- apiVersion: apps/v1 kind: StatefulSet metadata: name: web spec: selector: matchLabels: app: nginx serviceName: "nginx" # headless service的名字 replicas: 2 # 副本数 template: metadata: # 定义pod的模板 labels: app: nginx spec: containers: - name: nginx image: nginx ports: - containerPort: 80 # 容器服务的端口 name: web # 端口别名 volumeMounts: - name: www mountPath: /usr/share/nginx/html volumeClaimTemplates: # 存储卷申请模板 - metadata: name: www spec: accessModes: ["ReadWriteOnce"] # 访问模式:单路读写 storageClassName: "nfs" # 指定从哪个存储类申请pv resources: requests: storage: 1Gi # 需要1G的pvc,会自动跟符合条件的pv绑定 3.2、更新资源清单文件[root@master 12]# kubectl apply -f statefulset.yaml service/nginx created statefulset.apps/web created # 查看statefulset是否创建成功 [root@master 12]# kubectl get statefulset NAME READY AGE web 2/2 2m7s # 查看pod [root@master 12]# kubectl get pods -l app=nginx NAME READY STATUS RESTARTS AGE web-0 1/1 Running 0 2m50s web-1 1/1 Running 0 2m8s # 通过上面可以看到创建的pod是有序的3.3、查看相关资源[root@master 12]# kubectl get svc -l app=nginx NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx ClusterIP None <none> 80/TCP 3m50s [root@master 12]# kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE www-web-0 Bound pvc-223fc042-1b1b-4516-a1b5-a5572434d3ee 1Gi RWO nfs 4m8s www-web-1 Bound pvc-b4f026b2-4984-4302-b45d-00c57a74a162 1Gi RWO nfs 3m26s [root@master 12]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-223fc042-1b1b-4516-a1b5-a5572434d3ee 1Gi RWO Delete Bound default/www-web-0 nfs 4m39s pvc-b4f026b2-4984-4302-b45d-00c57a74a162 1Gi RWO Delete Bound default/www-web-1 nfs 3m56s [root@master 12]# for i in 0 1; do kubectl exec web-$i -- sh -c 'hostname';done web-0 web-1四、StatefulSet组成部分4.1、 Headless Service用来定义pod网路标识,生成可解析的DNS记录Headless service不分配clusterIP,headless service可以通过解析service的DNS,返回所有Pod的dns和ip地址 (statefulSet部署的Pod才有DNS),普通的service,只能通过解析service的DNS返回service的ClusterIP。【1】headless service会为service分配一个域名<service name>.$<namespace name>.svc.cluster.localK8s中资源的全局FQDN格式:  Service_NAME.NameSpace_NAME.Domain.LTD.  Domain.LTD.=svc.cluster.local #这是默认k8s集群的域名。扩展:FQDNFQDN 全称 Fully Qualified Domain Name即全限定域名:同时带有主机名和域名的名称FQDN = Hostname + DomainName如 主机名是 xianchao 域名是 baidu.comFQDN= xianchao.baidu.com【2】StatefulSet会为关联的Pod保持一个不变的Pod Namestatefulset中Pod的名字格式为$(StatefulSet name)-$(pod序号)【3】StatefulSet会为关联的Pod分配一个dnsName$<Pod Name>.$<service name>.$<namespace name>.svc.cluster.local4.2、volumeClaimTemplates为什么要用volumeClaimTemplate?对于有状态应用都会用到持久化存储,比如mysql主从,由于主从数据库的数据是不能存放在一个目录下的,每个mysql节点都需要有自己独立的存储空间。而在deployment中创建的存储卷是一个共享的存储卷,多个pod使用同一个存储卷,它们数据是同步的,而statefulset定义中的每一个pod都不能使用同一个存储卷,这就需要使用volumeClainTemplate。当在使用statefulset创建pod时,volumeClainTemplate会自动生成一个PVC,从而请求绑定一个PV,每一个pod都有自己专用的存储卷。Pod、PVC和PV对应的关系图如下:使用kubectl run运行一个提供nslookup命令的容器,这个命令来自于dnsutils包,通过对pod主机名执行nslookup,可以检查它们在集群内部的DNS地址kubectl run busybox --image docker.io/library/busybox:1.28 --image-pull-policy=IfNotPresent --restart=Never --rm -it busybox -- sh If you don't see a command prompt, try pressing enter. / # nslookup web-0.nginx.default.svc.cluster.local Server: 10.96.0.10 Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local Name: web-0.nginx.default.svc.cluster.local # 查询service dns,会把对应的pod ip解析出来 Address 1: 10.244.196.144 web-0.nginx.default.svc.cluster.local4.3、总结1、Statefulset管理的pod,pod名字是有序的,由statefulset的名字-0、1、2这种格式组成2、创建statefulset资源的时候,必须事先创建好一个service,如果创建的service没有ip,那对这个service做dns解析,会找到它所关联的pod ip,如果创建的service有ip,那对这个service做dns解析,会解析到service本身ip。3、statefulset管理的pod,删除pod,新创建的pod名字跟删除的pod名字是一样的4、statefulset具有volumeclaimtemplate这个字段,这个是卷申请模板,会自动创建pv,pvc也会自动生成,跟pv进行绑定,那如果创建的statefulset使用了volumeclaimtemplate这个字段,那创建pod,数据目录是独享的5、ststefulset创建的pod,是有域名的(域名组成:pod-name.svc-name.svc-namespace.svc.cluster.local)五、Statefulset管理pod:扩容、缩容、更新5.1、动态扩缩容如果我们觉得两个副本太少了,想要增加,只需要修改配置文件statefulset.yaml里的replicas的值即可,原来replicas: 2,现在变成replicaset: 3,修改之后,执行如下命令更新:[root@master 12]# kubectl apply -f statefulset.yaml service/nginx unchanged statefulset.apps/web configured [root@master 12]# kubectl get sts NAME READY AGE web 3/3 80m [root@master 12]# kubectl get pods -l app=nginx NAME READY STATUS RESTARTS AGE web-0 1/1 Running 0 81m web-1 1/1 Running 0 80m web-2 1/1 Running 0 28s也可以直接编辑控制器实现扩容,这个是我们把请求提交给了apiserver,实时修改[root@master 12]# kubectl edit sts web # 副本改成4 statefulset.apps/web edited [root@master 12]# kubectl get pods -l app=nginx NAME READY STATUS RESTARTS AGE web-0 1/1 Running 0 82m web-1 1/1 Running 0 81m web-2 1/1 Running 0 90s web-3 1/1 Running 0 7s5.2、滚动更新kubectl explain sts.spec.updateStrategy[root@master 12]# kubectl explain sts.spec.updateStrategy KIND: StatefulSet VERSION: apps/v1 RESOURCE: updateStrategy <Object> DESCRIPTION: updateStrategy indicates the StatefulSetUpdateStrategy that will be employed to update Pods in the StatefulSet when a revision is made to Template. StatefulSetUpdateStrategy indicates the strategy that the StatefulSet controller will use to perform updates. It includes any additional parameters necessary to perform the update for the indicated strategy. FIELDS: rollingUpdate <Object> RollingUpdate is used to communicate parameters when Type is RollingUpdateStatefulSetStrategyType. type <string> Type indicates the type of the StatefulSetUpdateStrategy. Default is RollingUpdate Possible enum values: - `"OnDelete"` - `"RollingUpdate"` [root@master 12]# cat statefulset.yaml apiVersion: v1 kind: Service metadata: name: nginx labels: app: nginx spec: ports: - port: 80 name: web clusterIP: None selector: app: nginx --- apiVersion: apps/v1 kind: StatefulSet metadata: name: web spec: updateStrategy: # 1、添加更新策略 rollingUpdate: partition: 1 # 序号大于等于1的pod做更新 maxUnavailable: 0 # 滚动更新时允许不可用 Pod 的最大数量 selector: matchLabels: app: nginx serviceName: "nginx" replicas: 3 template: metadata: labels: app: nginx spec: containers: - name: nginx image: ikubernetes/myapp:v2 # 2、修改镜像:容器才会更新 imagePullPolicy: IfNotPresent ports: - containerPort: 80 name: web volumeMounts: - name: www mountPath: /usr/share/nginx/html volumeClaimTemplates: - metadata: name: www spec: accessModes: ["ReadWriteOnce"] storageClassName: "nfs" resources: requests: storage: 1Gi# 在一个终端执行如下命令:kubectl apply -f statefulset.yaml # 在另一个终端动态查看pod [root@master ~]# kubectl get pods -l app=nginx -w NAME READY STATUS RESTARTS AGE web-0 1/1 Running 0 102m web-1 1/1 Running 0 101m web-2 1/1 Running 0 22m web-3 1/1 Running 0 20m web-3 1/1 Terminating 0 20m web-3 1/1 Terminating 0 20m web-3 0/1 Terminating 0 20m web-3 0/1 Terminating 0 20m web-3 0/1 Terminating 0 20m web-2 1/1 Terminating 0 22m web-2 1/1 Terminating 0 22m web-2 0/1 Terminating 0 22m web-2 0/1 Terminating 0 22m web-2 0/1 Terminating 0 22m web-2 0/1 Pending 0 0s web-2 0/1 Pending 0 0s web-2 0/1 ContainerCreating 0 0s web-2 0/1 ContainerCreating 0 1s web-2 1/1 Running 0 10s web-1 1/1 Terminating 0 102m web-1 1/1 Terminating 0 102m web-1 0/1 Terminating 0 102m web-1 0/1 Terminating 0 102m web-1 0/1 Terminating 0 102m web-1 0/1 Pending 0 0s web-1 0/1 Pending 0 0s web-1 0/1 ContainerCreating 0 0s web-1 0/1 ContainerCreating 0 0s web-1 1/1 Running 0 9s web-2 1/1 Running 0 42s web-1 1/1 Running 0 52s # 从上面结果可以看出来,pod在更新的时候,只是更新了web-1、2、3 # partition: 1表示更新的时候会把pod序号大于等于1的进行更新如果更新策略是OnDelete,那不会自动更新pod,需要手动删除,重新常见的pod才会实现更新修改策略: updateStrategy: type: OnDelete # rollingUpdate: # partition: 1 # maxUnavailable: 0[root@master 12]# kubectl apply -f statefulset.yaml service/nginx unchanged statefulset.apps/web configured [root@master 12]# kubectl get pod -l app=nginx NAME READY STATUS RESTARTS AGE web-0 1/1 Running 0 121m web-1 1/1 Running 0 18m web-2 1/1 Running 0 18m [root@master 12]# kubectl delete pod web-0 pod "web-0" deleted # 在另一种终端动态查看 [root@master ~]# kubectl get pod -w NAME READY STATUS RESTARTS AGE web-0 1/1 Running 0 122m web-1 1/1 Running 0 19m web-2 1/1 Running 0 19m web-0 1/1 Terminating 0 122m web-0 1/1 Terminating 0 122m web-0 0/1 Terminating 0 122m web-0 0/1 Terminating 0 122m web-0 0/1 Terminating 0 122m web-0 0/1 Pending 0 0s web-0 0/1 Pending 0 0s web-0 0/1 ContainerCreating 0 0s web-0 0/1 ContainerCreating 0 1s web-0 1/1 Running 0 2s
0
0
0
浏览量2019
锅从天上来

【Kubernetes】kubeadm安装k8s1.25.0高可用集群

一、初始化实验环境详情请参考 :【Kubernetes】kubeadm安装k8s稳定版(1.23.1)高可用集群这里不再赘述这部分内容还没发布。。。后续有空再整理更新啦。二、安装containerd服务2.1、安装containerdmaster、node节点都需要操作# 1、安装 yum install containerd.io-1.6.6 -y # 2、生成containerd配置文件 mkdir -p /etc/containerd containerd config default > /etc/containerd/config.toml # 3、修改配置文件 vim /etc/containerd/config.toml # 把SystemdCgroup = false修改成 SystemdCgroup = true # 把sandbox_image = "k8s.gcr.io/pause:3.6"修改成 sandbox_image="registry.aliyuncs.com/google_containers/pause:3.7" # 4、配置 containerd 开机启动,并启动 containerd systemctl enable containerd --now# 5、修改/etc/crictl.yaml文件 cat > /etc/crictl.yaml <<EOF runtime-endpoint: unix:///run/containerd/containerd.sock image-endpoint: unix:///run/containerd/containerd.sock timeout: 10 debug: false EOF # 6、重启contaiinerd systemctl restart containerd2.2、安装dockerdocker也要安装,docker跟containerd不冲突,安装docker是为了能基于dockerfile构建镜像。master、node节点都需要操作yum install docker-ce -y systemctl enable docker --now2.3、配置镜像加速器# 1、配置containerd镜像加速器,k8s所有节点均按照以下配置: # 编辑vim /etc/containerd/config.toml文件 # 找到config_path = "",修改成如下目录: config_path = "/etc/containerd/certs.d" # 2、添加/etc/containerd/certs.d/docker.io/hosts.toml文件 mkdir /etc/containerd/certs.d/docker.io/ -p vim /etc/containerd/certs.d/docker.io/hosts.toml #写入如下内容: [host."https://vh3bm52y.mirror.aliyuncs.com",host."https://registry.docker-cn.com"] capabilities = ["pull"] # 3、重启containerd: systemctl restart containerd # 4、配置docker镜像加速器,k8s所有节点均按照以下配置 vim /etc/docker/daemon.json # 写入如下内容: { "registry-mirrors":["https://vh3bm52y.mirror.aliyuncs.com","https://registry.docker-cn.com","https://docker.mirrors.ustc.edu.cn","https://dockerhub.azk8s.cn","http://hub-mirror.c.163.com"] } # 5、重启docker: systemctl restart docker三、安装初始化k8s需要的软件包3台机器都要安装yum install -y kubelet-1.25.0 kubeadm-1.25.0 kubectl-1.25.0 systemctl enable kubelet注:每个软件包的作用Kubeadm: kubeadm是一个工具,用来初始化k8s集群的kubelet: 安装在集群所有节点上,用于启动Pod的,kubeadm安装k8s,k8s控制节点和工作节点的组件,都是基于pod运行的,只要pod启动,就需要kubeletkubectl: 通过kubectl可以部署和管理应用,查看各种资源,创建、删除和更新各种组件四、kubeadm初始化k8s集群4.1、设置容器运行时[root@master ~]# crictl config runtime-endpoint /run/containerd/containerd.sock [root@node01 ~]# crictl config runtime-endpoint /run/containerd/containerd.sock [root@node02 ~]# crictl config runtime-endpoint /run/containerd/containerd.sock 4.2、生成并修改配置文件kubeadm config print init-defaults > kubeadm.yamlkubeadm.yaml一定要自己通过kubeadm config print init-defaults命令生成,根据我们自己的需求修改配置,比如修改 imageRepository 的值,kube-proxy 的模式为 ipvs,需要注意的是由于我们使用的containerd作为运行时,所以在初始化节点的时候需要指定cgroupDriver为systemdvim kubeadm.yamlapiVersion: kubeadm.k8s.io/v1beta3 bootstrapTokens: - groups: - system:bootstrappers:kubeadm:default-node-token token: abcdef.0123456789abcdef ttl: 24h0m0s usages: - signing - authentication kind: InitConfiguration localAPIEndpoint: advertiseAddress: 10.32.1.147 # 控制节点的ip bindPort: 6443 nodeRegistration: criSocket: unix:///run/containerd/containerd.sock # 指定containerd容器运行时 imagePullPolicy: IfNotPresent name: master # 控制节点主机名 taints: null --- apiServer: timeoutForControlPlane: 4m0s apiVersion: kubeadm.k8s.io/v1beta3 certificatesDir: /etc/kubernetes/pki clusterName: kubernetes controllerManager: {} dns: {} etcd: local: dataDir: /var/lib/etcd imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers # 指定阿里云镜像仓库地址 kind: ClusterConfiguration kubernetesVersion: 1.25.0 # k8s版本 networking: dnsDomain: cluster.local podSubnet: 10.244.0.0/16 # 指定pod网段, 需要新增加这个 serviceSubnet: 10.96.0.0/12 scheduler: {} # 最后追加插入以下这8行 --- apiVersion: kubeproxy.config.k8s.io/v1alpha1 kind: KubeProxyConfiguration mode: ipvs # 生成防火请规则存入ipvs,否则就存入iptables里面了 --- apiVersion: kubelet.config.k8s.io/v1beta1 kind: KubeletConfiguration cgroupDriver: systemd # kubelet驱动4.2、初始化安装kubeadm init --config=kubeadm.yaml --ignore-preflight-errors=SystemVerification显示如下,说明安装完成:特别提醒:–image-repository registry.aliyuncs.com/google_containers为保证拉取镜像不到国外站点拉取,手动指定仓库地址为registry.aliyuncs.com/google_containers。kubeadm默认从k8s.gcr.io拉取镜像。mode: ipvs 表示kube-proxy代理模式是ipvs,如果不指定ipvs,会默认使用iptables,但是iptables效率低,所以我们生产环境建议开启ipvs,阿里云和华为云托管的K8s,也提供ipvs模式,如下:4.3、修改config文件,对kubectl进行授权[root@master ~]# mkdir -p $HOME/.kube [root@master ~]# mkdir -p $HOME/.kube [root@master ~]# sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config [root@master ~]# sudo chown $(id -u):$(id -g) $HOME/.kube/config [root@master ~]# kubectl get nodes NAME STATUS ROLES AGE VERSION master NotReady control-plane 11m v1.25.0 # 备注:NotReady表示没装网络插件 [root@master ~]# kubectl get pods -n kube-system -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES coredns-7f8cbcb969-hfscf 0/1 Pending 0 12m <none> <none> <none> <none> coredns-7f8cbcb969-lvd69 0/1 Pending 0 12m <none> <none> <none> <none> etcd-master 1/1 Running 0 12m 10.32.1.147 master <none> <none> kube-apiserver-master 1/1 Running 0 12m 10.32.1.147 master <none> <none> kube-controller-manager-master 1/1 Running 0 12m 10.32.1.147 master <none> <none> kube-proxy-zr9fq 1/1 Running 0 12m 10.32.1.147 master <none> <none> kube-scheduler-master 1/1 Running 0 12m 10.32.1.147 master <none> <none> # 注意:上面coredns是pending状态,没装网络插件,正常,等装完网络插件,就变成running五、扩容k8s集群-添加工作节点5.1、 kubeadm joinnode01、node02上面都要操作[root@master ~]# kubeadm token create --print-join-command kubeadm join 10.32.1.147:6443 --token mjtwr8.0q4kj2lyccm0ldnw --discovery-token-ca-cert-hash sha256:d0e45daeda533addf757b5e89d0d2dbe1c00375cacab40bcaf07b1fb55b81148 [root@node01 ~]# kubeadm join 10.32.1.147:6443 --token mjtwr8.0q4kj2lyccm0ldnw --discovery-token-ca-cert-hash sha256:d0e45daeda533addf757b5e89d0d2dbe1c00375cacab40bcaf07b1fb55b81148 [root@node02 ~]# kubeadm join 10.32.1.147:6443 --token mjtwr8.0q4kj2lyccm0ldnw --discovery-token-ca-cert-hash sha256:d0e45daeda533addf757b5e89d0d2dbe1c00375cacab40bcaf07b1fb55b81148出现以下结果代表加入成功:5.2、节点打标签# 查看集群节点状况 [root@master ~]# kubectl get node NAME STATUS ROLES AGE VERSION master NotReady control-plane 38m v1.25.0 node01 NotReady <none> 3m v1.25.0 node02 NotReady <none> 108s v1.25.0 # 对node节点打标签,显示work [root@master ~]# kubectl label nodes node01 node-role.kubernetes.io/work=work node/node01 labeled [root@master ~]# kubectl label nodes node02 node-role.kubernetes.io/work=work node/node02 labeled [root@master ~]# kubectl get nodes NAME STATUS ROLES AGE VERSION master NotReady control-plane 45m v1.25.0 node01 NotReady work 10m v1.25.0 node02 NotReady work 9m34s v1.25.05.3、工作节点执行kubectl目前工作节点是不能执行kubectl的,因为工作节点上没有$HOME/.kube/config文件。[root@node01 ~]# kubectl get nodes The connection to the server localhost:8080 was refused - did you specify the right host or port? You have new mail in /var/spool/mail/root [root@node01 ~]# mkdir $HOME/.kube/ You have new mail in /var/spool/mail/root [root@node02 ~]# mkdir $HOME/.kube/ You have new mail in /var/spool/mail/root # 将config文件copy到节点的对应位置 [root@master ~]# scp /root/.kube/config node01:/root/.kube/ config 100% 5635 396.5KB/s 00:00 [root@master ~]# scp /root/.kube/config node02:/root/.kube/ config 100% 5635 2.5MB/s 00:00 # 这样就可以使用kubectl 命令了 [root@node01 ~]# kubectl get nodes NAME STATUS ROLES AGE VERSION master NotReady control-plane 52m v1.25.0 node01 NotReady work 16m v1.25.0 node02 NotReady work 15m v1.25.0 You have new mail in /var/spool/mail/root [root@node02 ~]# kubectl get nodes NAME STATUS ROLES AGE VERSION master NotReady control-plane 52m v1.25.0 node01 NotReady work 16m v1.25.0 node02 NotReady work 15m v1.25.0 You have new mail in /var/spool/mail/root六、安装kubernetes网络组件-Calico6.1、组件安装上传calico.yaml到master上,使用yaml文件安装calico 网络插件 。注:在线下载配置文件地址是: https://docs.projectcalico.org/manifests/calico.yaml[root@master ~]# kubectl apply -f calico.yaml [root@master ~]# kubectl get node NAME STATUS ROLES AGE VERSION master Ready control-plane 62m v1.25.0 node01 Ready work 26m v1.25.0 node02 Ready work 25m v1.25.06.2、Calico架构图Calico网络模型主要工作组件:1.Felix:运行在每一台 Host 的 agent 进程,主要负责网络接口管理和监听、路由、ARP 管理、ACL 管理和同步、状态上报等。保证跨主机容器网络互通。2.etcd:分布式键值存储,相当于k8s集群中的数据库,存储着Calico网络模型中IP地址等相关信息。主要负责网络元数据一致性,确保 Calico 网络状态的准确性;3.BGP Client(BIRD):Calico 为每一台 Host 部署一个 BGP Client,即每台host上部署一个BIRD。 主要负责把 Felix 写入 Kernel 的路由信息分发到当前 Calico 网络,确保 Workload 间的通信的有效性;4.BGP Route Reflector:在大型网络规模中,如果仅仅使用 BGP client 形成 mesh 全网互联的方案就会导致规模限制,因为所有节点之间俩俩互联,需要 N^2 个连接,为了解决这个规模问题,可以采用 BGP 的 Router Reflector 的方法,通过一个或者多个 BGP Route Reflector 来完成集中式的路由分发。6.3、 calico网络插件配置文件说明calico.yam文件中…… containers: # Runs calico-node container on each Kubernetes node. This # container programs network policy and routes on each # host. - name: calico-node image: docker.io/calico/node:v3.18.0 …… env: # Use Kubernetes API as the backing datastore. - name: DATASTORE_TYPE value: "kubernetes" # Cluster type to identify the deployment type - name: CLUSTER_TYPE value: "k8s,bgp" # Auto-detect the BGP IP address. - name: IP value: "autodetect" #pod网段 - name: CALICO_IPV4POOL_CIDR value: "10.244.0.0/16" # Enable IPIP - name: CALICO_IPV4POOL_IPIP value: "Always" calico-node服务的主要参数如下:CALICO_IPV4POOL_IPIP:是否启用IPIP模式。启用IPIP模式时,Calico将在Node上创建一个名为tunl0的虚拟隧道。IP Pool可以使用两种模式:BGP或IPIP。使用IPIP模式时,设置CALICO_IPV4POOL_IPIP=“Always”,不使用IPIP模式时,设置CALICO_IPV4POOL_IPIP=“Off”,此时将使用BGP模式。IP_AUTODETECTION_METHOD:获取Node IP地址的方式,默认使用第1个网络接口的IP地址,对于安装了多块网卡的Node,可以使用正则表达式选择正确的网卡,例如"interface=eth.*"表示选择名称以eth开头的网卡的IP地址。- name: IP_AUTODETECTION_METHOD value: "interface=ens33"6.4、calico的IPIP模式和BGP模式对比分析1)IPIP把一个IP数据包又套在一个IP包里,即把IP层封装到IP层的一个 tunnel,它的作用其实基本上就相当于一个基于IP层的网桥,一般来说,普通的网桥是基于mac层的,根本不需要IP,而这个ipip则是通过两端的路由做一个tunnel,把两个本来不通的网络通过点对点连接起来;calico以ipip模式部署完毕后,node上会有一个tunl0的网卡设备,这是ipip做隧道封装用的,也是一种overlay模式的网络。当我们把节点下线,calico容器都停止后,这个设备依然还在,执行 rmmodipip命令可以将它删除。2)BGPBGP模式直接使用物理机作为虚拟路由路(vRouter),不再创建额外的tunnel边界网关协议(BorderGateway Protocol, BGP)是互联网上一个核心的去中心化的自治路由协议。它通过维护IP路由表或‘前缀’表来实现自治系统(AS)之间的可达性,属于矢量路由协议。BGP不使用传统的内部网关协议(IGP)的指标,而是基于路径、网络策略或规则集来决定路由。因此,它更适合被称为矢量性协议,而不是路由协议,通俗的说就是将接入到机房的多条线路(如电信、联通、移动等)融合为一体,实现多线单IP;BGP 机房的优点:服务器只需要设置一个IP地址,最佳访问路由是由网络上的骨干路由器根据路由跳数与其它技术指标来确定的,不会占用服务器的任何系统;官方提供的calico.yaml模板里,默认打开了ip-ip功能,该功能会在node上创建一个设备tunl0,容器的网络数据会经过该设备被封装一个ip头再转发。这里,calico.yaml中通过修改calico-node的环境变量:CALICO_IPV4POOL_IPIP来实现ipip功能的开关:默认是Always,表示开启;Off表示关闭ipip。6.5、测试k8s网络和dns是否正常 [root@master ~]# kubectl run busybox --image docker.io/library/busybox:1.28 --image-pull-policy=IfNotPresent --restart=Never --rm -it busybox -- sh If you don't see a command prompt, try pressing enter. / # ping www.baidu.com PING www.baidu.com (110.242.68.3): 56 data bytes 64 bytes from 110.242.68.3: seq=0 ttl=48 time=32.680 ms 64 bytes from 110.242.68.3: seq=1 ttl=48 time=32.587 ms ^C --- www.baidu.com ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 32.587/32.633/32.680 ms 通过上面可以看到能访问网络,说明calico网络插件已经被正常安装了。/ # nslookup kubernetes.default.svc.cluster.local Server: 10.96.0.10 Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local Name: kubernetes.default.svc.cluster.local Address 1: 10.96.0.1 kubernetes.default.svc.cluster.local10.96.0.10 就是我们coreDNS的clusterIP,说明coreDNS配置好了。解析内部Service的名称,是通过coreDNS去解析的。注意:busybox要用指定的1.28版本,不能用最新版本,最新版本,nslookup会解析不到dns和ip6.6、ctr和crictl区别背景:在部署k8s的过程中,经常要对镜像进行操作(拉取、删除、查看等)问题:使用过程中会发现ctr和crictl有很多相同功能,也有些不同,那区别到底在哪里?说明:1.ctr是containerd自带的CLI命令行工具,crictl是k8s中CRI(容器运行时接口)的客户端,k8s使用该客户端和containerd进行交互;2.ctr和crictl命令具体区别如下,也可以–help查看。crictl缺少对具体镜像的管理能力,可能是k8s层面镜像管理可以由用户自行控制,能配置pod里面容器的统一镜像仓库,镜像的管理可以有habor等插件进行处理。
0
0
0
浏览量2030
锅从天上来

【Kubernetes】四层代理Service

一、Service概念原理1.1、为什么要有Service在kubernetes中,Pod是有生命周期的,如果Pod重启它的IP很有可能会发生变化。如果我们的服务都是将Pod的IP地址写死,Pod挂掉或者重启,和刚才重启的pod相关联的其他服务将会找不到它所关联的Pod.为了解决这个问题,在kubernetes中定义了service资源对象,Service 定义了一个服务访问的入口,客户端通过这个入口即可访问服务背后的应用集群实例,service是一组Pod的逻辑集合,这一组Pod能够被Service访问到,通常是通过Label Selector实现的。pod ip经常变化,service是pod的代理,我们客户端访问,只需要访问service,就会把请求代理到Podpod ip在k8s集群之外无法访问,所以需要创建service,这个service可以在k8s集群外访问的。1.2、Service概述service是一个固定接入层,客户端可以通过访问service的ip和端口访问到service关联的后端pod。这个service工作依赖于在kubernetes集群之上部署的一个附件,就是kubernetes的dns服务(不同kubernetes版本的dns默认使用的也是不一样的,1.11之前的版本使用的是kubeDNs,较新的版本使用的是coredns)service的名称解析是依赖于dns附件的,因此在部署完k8s之后需要再部署dns附件,kubernetes要想给客户端提供网络功能,需要依赖第三方的网络插件(flannel,calico等)。每个K8s节点上都有一个组件叫做kube-proxy,kube-proxy这个组件将始终监视着apiserver中有关service资源的变动信息,需要跟master之上的apiserver交互,随时连接到apiserver上获取任何一个与service资源相关的资源变动状态这种是通过kubernetes中固有的一种请求方法watch(监视)来实现的,一旦有service资源的内容发生变动(如创建,删除),kube-proxy都会将它转化成当前节点之上的能够实现service资源调度,把我们请求调度到后端特定的pod资源之上的规则,这个规则可能是iptables,也可能是ipvs,取决于service的实现方式。1.3、工作原理k8s在创建Service时,会根据标签选择器selector(lable selector)来查找Pod,据此创建与Service同名的endpoint对象,当Pod 地址发生变化时,endpoint也会随之发生变化,service接收前端client请求的时候,就会通过endpoint,找到转发到哪个Pod进行访问的地址。(至于转发到哪个节点的Pod,由负载均衡kube-proxy决定)1.4、三类IP地址【1】Node Network(节点网络)物理节点或者虚拟节点的网络,如ens33接口上的网路地址[root@master ~]# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:9d:0d:9f brd ff:ff:ff:ff:ff:ff inet 10.32.1.147/24 brd 10.32.1.255 scope global noprefixroute ens32 valid_lft forever preferred_lft forever inet6 fe80::bdc4:94e0:2ba5:e504/64 scope link noprefixroute valid_lft forever preferred_lft forever【2】Pod network(pod 网络创建的Pod具有的IP地址[root@master ~]# kubectl get pods -A -o wide NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES kube-system calico-kube-controllers-6744f6b6d5-4vnx4 1/1 Running 0 27h 10.244.196.129 node01 <none> <none> kube-system calico-node-c7hdk 1/1 Running 0 27h 10.32.1.147 master <none> <none> kube-system calico-node-v8lg8 1/1 Running 0 27h 10.32.1.148 node01 <none> <none> kube-system calico-node-w8tkz 1/1 Running 0 27h 10.32.1.149 node02 <none> <none>Node Network和Pod network这两种网络地址是我们实实在在配置的,其中节点网络地址是配置在节点接口之上,而pod网络地址是配置在pod资源之上的,因此这些地址都是配置在某些设备之上的,这些设备可能是硬件,也可能是软件模拟的【3】Cluster Network(服务网络)集群地址,也称为service network这个地址是虚拟的地址(virtual ip),没有配置在某个接口上,只是出现在service的规则当中。[root@master ~]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 28h二、Service资源创建2.1、service资源字段[root@master1 ~]# kubectl explain service KIND: Service VERSION: v1 DESCRIPTION: Service is a named abstraction of software service (for example, mysql) consisting of local port (for example 3306) that the proxy listens on, and the selector that determines which pods will answer requests sent through the proxy. FIELDS: apiVersion <string> # service资源使用的api组 kind <string> # 创建的资源类型 metadata <Object> # 定义元数据 spec <Object> 2.2、service的spec字段定义[root@xianchaomaster1 ~]# kubectl explain service.spec KIND: Service VERSION: v1 RESOURCE: spec <Object> DESCRIPTION: Spec defines the behavior of a service. https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status ServiceSpec describes the attributes that a user creates on a service. FIELDS: allocateLoadBalancerNodePorts <boolean> clusterIP <string> # 动态分配的地址,也可以自己在创建的时候指定,创建之后就改不了了 clusterIPs <[]string> externalIPs <[]string> externalName <string> externalTrafficPolicy <string> healthCheckNodePort <integer> ipFamilies <[]string> ipFamilyPolicy <string> loadBalancerIP <string> loadBalancerSourceRanges <[]string> ports <[]Object> # 定义service端口,用来和后端pod建立联系 publishNotReadyAddresses <boolean> selector <map[string]string> # 通过标签选择器选择关联的pod有哪些 sessionAffinity <string> sessionAffinityConfig <Object> # service在实现负载均衡的时候还支持sessionAffinity? # sessionAffinity什么意思? # 会话联系,默认是none,随机调度的(基于iptables规则调度的);如果我们定义sessionAffinity的client ip,那就表示把来自同一客户端的IP请求调度到同一个pod上 topologyKeys <[]string> type <string> #定义service的类型2.3、Service端口kubectl explain service.spec.ports 可以查看端口相关内容 nodePort : service在物理机映射的端口,默认在 30000-32767 之间port: service的端口,这个是k8s集群内部服务可访问的端口 targetPort是pod上的端口,从port和nodePort上来的流量,经过kube-proxy流入到后端pod的targetPort上,最后进入容器。2.4、Service类型kubectl explain service.spec.type可以查看service有那几种类型【1】ClusterIP类型[root@master 9]# cat pod_test.yaml apiVersion: apps/v1 kind: Deployment metadata: name: my-nginx spec: selector: matchLabels: run: my-nginx replicas: 2 template: metadata: labels: run: my-nginx spec: containers: - name: my-nginx image: nginx imagePullPolicy: IfNotPresent ports: - containerPort: 80 #pod中的容器需要暴露的端口 startupProbe: periodSeconds: 5 initialDelaySeconds: 60 timeoutSeconds: 10 httpGet: scheme: HTTP port: 80 path: / livenessProbe: periodSeconds: 5 initialDelaySeconds: 60 timeoutSeconds: 10 httpGet: scheme: HTTP port: 80 path: / readinessProbe: periodSeconds: 5 initialDelaySeconds: 60 timeoutSeconds: 10 httpGet: scheme: HTTP port: 80 path: /# 更新资源清单文件 [root@master 9]# kubectl apply -f pod_test.yaml # 查看pod ip [root@master 9]# kubectl get pods -l run=my-nginx -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES my-nginx-fc8c7b6c4-7j6hx 1/1 Running 0 2m12s 10.244.196.136 node01 <none> <none> my-nginx-fc8c7b6c4-h7xg6 1/1 Running 0 2m12s 10.244.140.79 node02 <none> <none> # curl <ip> 可以访问对应的pod以上pod如果被删除,就会重新生成pod,pod ip也会变化,所以需要在pod前端加一个固定接入层。接下来创建Service:# 查看pod标签 [root@master ~]# kubectl get pods --show-labels NAME READY STATUS RESTARTS AGE LABELS my-nginx-fc8c7b6c4-7j6hx 1/1 Running 0 4h53m pod-template-hash=fc8c7b6c4,run=my-nginx my-nginx-fc8c7b6c4-h7xg6 1/1 Running 0 4h53m pod-template-hash=fc8c7b6c4,run=my-nginx # 创建Service [root@master 9]# cat service_test.yaml apiVersion: v1 kind: Service metadata: name: my-nginx labels: run: my-nginx spec: type: ClusterIP ports: - port: 80 #service的端口,暴露给k8s集群内部服务访问 protocol: TCP targetPort: 80 #pod容器中定义的端口 selector: run: my-nginx #选择拥有run=my-nginx标签的pod上述yaml文件将创建一个 Service,具有标签run=my-nginx的Pod,目标TCP端口 80,并且在一个抽象的Service端口(targetPort:容器接收流量的端口;port:抽象的 Service 端口,可以使任何其它 Pod访问该 Service 的端口)上暴露。[root@master 9]# kubectl apply -f service_test.yaml service/my-nginx created [root@master 9]# kubectl get svc -l run=my-nginx NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE my-nginx ClusterIP 10.102.168.76 <none> 80/TCP 10s # 在k8s控制节点访问service的ip:端口就可以把请求代理到后端pod [root@master 9]# curl 10.102.168.76:80通过上面可以看到请求service IP:port跟直接访问pod ip:port看到的结果一样,这就说明service可以把请求代理到它所关联的后端pod注意:上面的10.102.168.76:80地址只能是在k8s集群内部可以访问,在外部无法访问,比方说我们想要通过浏览器访问,那么是访问不通的,如果想要在k8s集群之外访问,是需要把service type类型改成nodePort的。[root@master ~]# kubectl describe svc my-nginx Name: my-nginx Namespace: default Labels: run=my-nginx Annotations: <none> Selector: run=my-nginx Type: ClusterIP IP Family Policy: SingleStack IP Families: IPv4 IP: 10.102.168.76 IPs: 10.102.168.76 Port: <unset> 80/TCP TargetPort: 80/TCP Endpoints: 10.244.140.79:80,10.244.196.136:80 Session Affinity: None Events: <none> [root@master ~]# kubectl get ep my-nginx NAME ENDPOINTS AGE my-nginx 10.244.140.79:80,10.244.196.136:80 22mservice可以对外提供统一固定的ip地址,并将请求重定向至集群中的pod。其中“将请求重定向至集群中的pod”就是通过endpoint与selector协同工作实现。selector是用于选择pod,由selector选择出来的pod的ip地址和端口号,将会被记录在endpoint中。endpoint便记录了所有pod的ip地址和端口号。当一个请求访问到service的ip地址时,就会从endpoint中选择出一个ip地址和端口号,然后将请求重定向至pod中。具体把请求代理到哪个pod,需要的就是kube-proxy的轮询实现的。service不会直接到pod,service是直接到endpoint资源,就是地址加端口,再由endpoint再关联到pod。service只要创建完成,我们就可以直接解析它的服务名,每一个服务创建完成后都会在集群dns中动态添加一个资源记录,添加完成后我们就可以解析了,资源记录格式是:SVC_NAME.NS_NAME.DOMAIN.LTD.服务名.命名空间.域名后缀集群默认的域名后缀是svc.cluster.local.就像我们上面创建的my-nginx这个服务,它的完整名称解析就是my-nginx.default.svc.cluster.local[root@master ~]# kubectl exec -it my-nginx-fc8c7b6c4-7j6hx /bin/bash kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead. root@my-nginx-fc8c7b6c4-7j6hx:/# curl my-nginx.default.svc.cluster.local <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> html { color-scheme: light dark; } body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>【2】NodePort类型[root@master 9]# cat pod_nodeport.yaml apiVersion: apps/v1 kind: Deployment metadata: name: my-nginx-nodeport spec: selector: matchLabels: run: my-nginx-nodeport replicas: 2 template: metadata: labels: run: my-nginx-nodeport spec: containers: - name: my-nginx-nodeport-container image: nginx imagePullPolicy: IfNotPresent ports: - containerPort: 80 [root@master 9]# kubectl apply -f pod_nodeport.yaml deployment.apps/my-nginx-nodeport created [root@master 9]# kubectl get pods -l run=my-nginx-nodeport -owide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES my-nginx-nodeport-7776f84758-5nxmb 1/1 Running 0 22s 10.244.196.137 node01 <none> <none> my-nginx-nodeport-7776f84758-qlr5z 1/1 Running 0 22s 10.244.140.80 node02 <none> <none> [root@master 9]# cat service_nodeport.yaml apiVersion: v1 kind: Service metadata: name: my-nginx-nodeport labels: run: my-nginx-nodeport spec: type: NodePort ports: - port: 80 protocol: TCP targetPort: 80 nodePort: 30380 selector: run: my-nginx-nodeport [root@master 9]# kubectl apply -f service_nodeport.yaml service/my-nginx-nodeport created [root@master 9]# kubectl get svc -l run=my-nginx-nodeport NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE my-nginx-nodeport NodePort 10.107.198.159 <none> 80:30380/TCP 6s [root@master 9]# curl 10.107.198.159 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> html { color-scheme: light dark; } body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> ......注意: 10.107.198.159是k8s集群内部的service ip地址,只能在k8s集群内部访问,在集群外无法访问。在集群外访问service:curl 10.107.198.159:30380数据转发流程:客户端请求http://10.32.1.147:30380 ->docker0虚拟网卡:172.17.0.1:30380 ->10.244.140.80:80,10.244.196.137:80[root@master 9]# ipvsadm -Ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 172.17.0.1:30380 rr # 172.17.0.1是docker0 网卡地址 -> 10.244.140.80:80 # pod1 ip Masq 1 0 0 -> 10.244.196.137:80 # pod2 ip Masq 1 0 0 TCP 10.32.1.147:30380 rr -> 10.244.140.80:80 Masq 1 0 0 -> 10.244.196.137:80 Masq 1 0 0 ......【3】ExternalName类型应用场景:跨名称空间访问需求:default名称空间下的client 服务想要访问nginx-ns名称空间下的nginx-svc服务步骤:1、创建名为nginx的pod (指定命名空间nginx-ns )# 在线拉取镜像(node节点上要操作) [root@node01 ~]# ctr images pull docker.io/library/busybox:latest [root@node01 ~]# ctr image ls|grep busy docker.io/library/busybox:latest application/vnd.docker.distribution.manifest.list.v2+json sha256:1ceb872bcc68a8fcd34c97952658b58086affdcb604c90c1dee2735bde5edc2f 2.1 MiB linux/386,linux/amd64,linux/arm/v5,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/mips64le,linux/ppc64le,linux/riscv64,linux/s390x - You have new mail in /var/spool/mail/root [root@master 9]# kubectl create ns nginx-ns namespace/nginx-ns created [root@master 9]# cat server_nginx.yaml apiVersion: apps/v1 kind: Deployment metadata: name: nginx namespace: nginx-ns spec: replicas: 1 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent [root@master 9]# kubectl apply -f server_nginx.yaml deployment.apps/nginx created [root@master 9]# kubectl get pods -n nginx-ns NAME READY STATUS RESTARTS AGE nginx-6fb6c59b65-56sxx 1/1 Running 0 4s2、创建名为nginx-svc的svc(指定命名空间nginx-ns )# 创建名为nginx-svc的svc [root@master 9]# cat nginx_svc.yaml apiVersion: v1 kind: Service metadata: name: nginx-svc namespace: nginx-ns spec: selector: app: nginx ports: - name: http protocol: TCP port: 80 targetPort: 80 [root@master 9]# kubectl apply -f nginx_svc.yaml service/nginx-svc created [root@master 9]# kubectl get svc -n nginx-ns NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx-svc ClusterIP 10.104.157.106 <none> 80/TCP 24s3、创建名为client的pod[root@master 9]# cat client.yaml apiVersion: apps/v1 kind: Deployment metadata: name: client spec: replicas: 1 selector: matchLabels: app: busybox template: metadata: labels: app: busybox spec: containers: - name: busybox image: busybox imagePullPolicy: IfNotPresent command: ["/bin/sh","-c","sleep 36000"] [root@master 9]# kubectl apply -f client.yaml4、创建名为client-svc的svc# 创建名为client-svc的svc [root@master 9]# cat client_svc.yaml apiVersion: v1 kind: Service metadata: name: client-svc spec: type: ExternalName # 这里使用到了nginx-svc 的软链,让使用者感觉就好像调用自己命名空间的服务一样。 externalName: nginx-svc.nginx-ns.svc.cluster.local ports: - name: http port: 80 targetPort: 80 [root@master 9]# kubectl apply -f client_svc.yaml service/client-svc created[root@master 9]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE client-svc ExternalName <none> nginx-svc.nginx-ns.svc.cluster.local 80/TCP 5h4m kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 2d5h my-nginx ClusterIP 10.102.168.76 <none> 80/TCP 18h my-nginx-nodeport NodePort 10.107.198.159 <none> 80:30380/TCP 17h5、登录client pod[root@master 9]# kubectl exec -it client-568955849b-vglmj /bin/sh kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead. / # / # wget -q -O - client-svc.default.svc.cluster.local <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> ...... / # wget -q -O - nginx-svc.nginx-ns.svc.cluster.local <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> ...... # 上面两个请求的结果一样三、k8s最佳实践:映射外部服务案例分享k8s集群引用外部的mysql数据库在node02节点上安装mysql数据库[root@node02 ~]# yum install mariadb-server.x86_64 -y [root@node02 ~]# systemctl start mariadb [root@master 9]# cat mysql_service.yaml apiVersion: v1 kind: Service metadata: name: mysql spec: # 这里没有标签选择器,是不会关联到任何pod的 type: ClusterIP ports: - port: 3306 [root@master 9]# kubectl apply -f mysql_service.yaml service/mysql created [root@master 9]# kubectl get svc | grep mysql mysql ClusterIP 10.104.34.181 <none> 3306/TCP 6s [root@master 9]# kubectl describe svc mysql Name: mysql Namespace: default Labels: <none> Annotations: <none> Selector: <none> Type: ClusterIP IP Family Policy: SingleStack IP Families: IPv4 IP: 10.104.34.181 IPs: 10.104.34.181 Port: <unset> 3306/TCP TargetPort: 3306/TCP Endpoints: <none> # 没有endpoint Session Affinity: None Events: <none>接下来,我想做的是,创建endpoint,通过访问maysql的域名或ip能代理node2节点上的mysql# 创建endpoint资源 [root@master 9]# cat mysql_endpoint.yaml apiVersion: v1 kind: Endpoints metadata: name: mysql # 名字必须和要关联的svc名字一致 subsets: # subsets是一个对象列表,所有后面的子内容要加 - - addresses: - ip: 10.32.1.149 ports: - port: 3306 [root@master 9]# kubectl apply -f mysql_endpoint.yaml endpoints/mysql created [root@master 9]# kubectl get ep NAME ENDPOINTS AGE kubernetes 10.32.1.147:6443 4d1h my-nginx 10.244.140.79:80,10.244.196.136:80 2d14h my-nginx-nodeport 10.244.140.80:80,10.244.196.137:80 2d13h mysql 10.32.1.149:3306 43h [root@master 9]# kubectl describe svc mysql Name: mysql Namespace: default Labels: <none> Annotations: <none> Selector: <none> Type: ClusterIP IP Family Policy: SingleStack IP Families: IPv4 IP: 10.104.34.181 IPs: 10.104.34.181 Port: <unset> 3306/TCP TargetPort: 3306/TCP Endpoints: 10.32.1.149:3306 # 这个就是定义的外部数据库 Session Affinity: None Events: <none>上面配置就是将外部IP地址和服务引入到k8s集群内部,由service作为一个代理来达到能够访问外部服务的目的。四、Service服务发现:coredns组件详解4.1、DNS是什么?DNS全称是Domain Name System:域名系统,是整个互联网的电话簿,它能够将可被人理解的域名翻译成可被机器理解IP地址,使得互联网的使用者不再需要直接接触很难阅读和理解的IP地址。域名系统在现在的互联网中非常重要,因为服务器的 IP 地址可能会经常变动,如果没有了 DNS,那么可能 IP 地址一旦发生了更改,当前服务器的客户端就没有办法连接到目标的服务器了,如果我们为 IP 地址提供一个『别名』并在其发生变动时修改别名和 IP 地址的关系,那么我们就可以保证集群对外提供的服务能够相对稳定地被其他客户端访问。DNS 其实就是一个分布式的树状命名系统,它就像一个去中心化的分布式数据库,存储着从域名到 IP 地址的映射。4.2、CoreDNS是什么?CoreDNS 其实就是一个 DNS 服务,而 DNS 作为一种常见的服务发现手段,所以很多开源项目以及工程师都会使用 CoreDNS 为集群提供服务发现的功能,Kubernetes 就在集群中使用 CoreDNS 解决服务发现的问题。 作为一个加入 CNCF(Cloud Native Computing Foundation)的服务, CoreDNS 的实现非常简单。4.3、验证CoreDNSService完整的名称组成:<servicename>.<namespace>.svc.cluster.local那么k8s集群内部的服务就可以通过FQDN访问[root@master 9]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE client-svc ExternalName <none> nginx-svc.nginx-ns.svc.cluster.local 80/TCP 2d1h kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4d2h my-nginx ClusterIP 10.102.168.76 <none> 80/TCP 2d14h my-nginx-nodeport NodePort 10.107.198.159 <none> 80:30380/TCP 2d14h mysql ClusterIP 10.104.34.181 <none> # 比如这里的client # 完整的FQDN : client-svc.default.svc.class.local【1】导入镜像,运行pod# 把dig.tar.gz上传到xianchaonode2和xianchaonode1机器上,手动解压: [root@node01 ~]# ctr -n=k8s.io images import dig.tar.gz [root@node02 ~]# ctr -n=k8s.io images import dig.tar.gz [root@master 9]# cat dig.yaml apiVersion: v1 kind: Pod metadata: name: dig namespace: default spec: containers: - name: dig image: xianchao/dig:latest # 这个镜像其实就提供了一个命令 imagePullPolicy: IfnotPresent command: - sleep - "3600" imagePullPolicy: IfNotPresent restartPolicy: Always [root@master 9]# kubectl apply -f dig.yaml【2】dns解析# 查看默认名称空间的kubernetes服务 [root@master 9]# kubectl get svc | grep kubernetes kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4d2h # 查看默认名称空间的client服务 [root@master 9]# kubectl get svc | grep client client-svc ExternalName <none> nginx-svc.nginx-ns.svc.cluster.local 80/TCP 2d2h # 解析dns,如有以下返回说明dns安装成功 [root@master 9]# kubectl exec -it dig -- nslookup kubernetes Server: 10.96.0.10 # kube-dns这个svc的ip Address: 10.96.0.10#53 # 说明用的是对应cordns的pod进行域名解析 Name: kubernetes.default.svc.cluster.local # 域名 Address: 10.96.0.1 # ip [root@master 9]# kubectl exec -it dig -- nslookup client-svc Server: 10.96.0.10 Address: 10.96.0.10#53 client-svc.default.svc.cluster.local canonical name = nginx-svc.nginx-ns.svc.cluster.local. Name: nginx-svc.nginx-ns.svc.cluster.local # 域名 Address: 10.104.157.106 # ip
0
0
0
浏览量2020
锅从天上来

【Kubernetes】持久化存储emptyDir/hostPath/nfs/PVC

一、为什么做持久化存储?在k8s中部署的应用都是以pod容器的形式运行的,假如我们部署MySQL、Redis等数据库,需要对这些数据库产生的数据做备份。因为Pod是有生命周期的,如果pod不挂载数据卷,那pod被删除或重启后这些数据会随之消失,如果想要长久的保留这些数据就要用到pod数据持久化存储。查看k8s支持哪些存储 kubectl explain pods.spec.volumes常用的有emptyDir、hostPath 、nfs 、persistentVolumeClaim、glusterfs、cephfs、configMap、secret我们想要使用存储卷,需要经历如下步骤:1、定义pod的volume,这个volume指明它要关联到哪个存储上的2、在容器中要使用volumemounts挂载对应的存储二、k8s持久化存储:emptyDiremptyDir类型的Volume是在Pod分配到Node上时被创建,Kubernetes会在Node上自动分配一个目录,因此无需指定宿主机Node上对应的目录文件。这个目录的初始内容为空,当Pod从Node上移除时,emptyDir中的数据会被永久删除。emptyDir Volume主要用于某些应用程序无需永久保存的临时目录,多个容器的共享目录等。Emptydir的官方网址:https://kubernetes.io/docs/concepts/storage/volumes#emptydir# 创建一个pod,挂载临时目录emptyDir [root@master 10]# cat emptydir.yaml apiVersion: v1 kind: Pod metadata: name: pod-empty spec: containers: - name: container-empty image: nginx imagePullPolicy: IfNotPresent volumeMounts: - name: cache-volume # 将cache-volume的挂载到容器里面的/cache下 mountPath: /cache volumes: - emptyDir: {} # 把临时目录做成一个卷 name: cache-volume # 临时卷卷名 [root@master 10]# kubectl apply -f emptydir.yaml # 查看本机临时目录存在的位置,可用如下方法: # 查看pod调度到哪个节点 [root@master 10]# kubectl get pods -o wide | grep empty pod-empty 1/1 Running 0 85s 10.244.140.83 node02 <none> <none> [root@master 10]# kubectl get pods pod-empty -o yaml | grep uid uid: 3570ddfd-b4ab-4500-928e-caa3f369c276# 登录到对应节点上 [root@node02 ~]# yum install tree -y [root@node02 ~]# tree /var/lib/kubelet/pods/3570ddfd-b4ab-4500-928e-caa3f369c276 /var/lib/kubelet/pods/3570ddfd-b4ab-4500-928e-caa3f369c276 ├── containers │ └── container-empty │ └── e90c5eec ├── etc-hosts ├── plugins │ └── kubernetes.io~empty-dir │ ├── cache-volume │ │ └── ready │ └── wrapped_kube-api-access-896m7 │ └── ready └── volumes ├── kubernetes.io~empty-dir │ └── cache-volume # 临时目录 └── kubernetes.io~projected └── kube-api-access-896m7 ├── ca.crt -> ..data/ca.crt ├── namespace -> ..data/namespace └── token -> ..data/token缺点:pod删除后,对应的UID的目录就没有了,里面的临时目录也就没有了。所以,emptyDir只适合做测试用。三、k8s持久化存储:hostPathhostPath Volume是指Pod挂载宿主机上的目录或文件。 hostPath Volume使得容器可以使用宿主机的文件系统进行存储,hostpath(宿主机路径):节点级别的存储卷,在pod被删除,这个存储卷还是存在的,不会被删除所以只要同一个pod被调度到同一个节点上来,在pod被删除重新被调度到这个节点之后,对应的数据依然是存在的。查看hostPath存储卷的用法: kubectl explain pods.spec.volumes.hostPath# 创建一个pod,挂载hostPath存储卷 [root@master 10]# cat hostpath.yaml apiVersion: v1 kind: Pod metadata: name: test-hostpath spec: nodeName: node01 containers: - name: test-nginx image: nginx imagePullPolicy: IfNotPresent volumeMounts: - name: test-volume mountPath: /test-nginx - name: test-tomcat image: tomcat:8.5-jre8-alpine imagePullPolicy: IfNotPresent volumeMounts: - name: test-volume mountPath: /test-tomcat volumes: - hostPath: path: /data1 type: DirectoryOrCreate # 如果宿主机该目录不存在,则创建,权限设置为0755 name: test-volume [root@master 10]# kubectl apply -f hostpath.yaml [root@master 10]# kubectl get pod NAME READY STATUS RESTARTS AGE test-hostpath 2/2 Running 0 70s数据卷类型:https://kubernetes.io/zh-cn/docs/concepts/storage/volumes/由上面可以知道pod调度到了node01上,登录到node01机器,查看是否在这台机器创建了存储目录[root@node01 /]# ll -d data1 drwxr-xr-x 2 root root 6 Dec 10 20:38 data1 # 进入容器,创建文件 [root@master 10]# kubectl exec -it test-hostpath -c test-nginx /bin/bash kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead. root@test-hostpath:/# cd /test-nginx root@test-hostpath:/test-nginx# touch nginx root@test-hostpath:/test-nginx# ls nginx # 宿主机对应路径下存在该文件,说明已经把宿主机目录挂载到了容器里 [root@node01 /]# cd data1 [root@node01 data1]# ls nginx缺点:单节点。pod删除之后重新创建必须调度到同一个node节点,数据才不会丢失可以用分布式存储:nfs,cephfs,glusterfs四、k8s持久化存储:nfsNFS:网络文件系统,英文Network File System(NFS),是由SUN公司研制的UNIX表示层协议(presentation layer protocol),能使使用者访问网络上别处的文件就像在使用自己的计算机一样。4.1、搭建nfs服务# 1、以k8s的控制节点作为NFS服务 [root@master 10]# yum install nfs-utils -y # 2、在宿主机创建NFS需要的共享目录 [root@master 10]# mkdir /data/volumes -pv mkdir: created directory ‘/data/volumes’ # 3、配置nfs共享服务器上的/data/volumes目录 [root@master 10]# systemctl start nfs [root@master 10]# cat /etc/exports /data/volumes *(rw,no_root_squash) # rw 该主机对该共享目录有读写权限 # no_root_squash 登入 NFS 主机使用分享目录的使用者,如果是 root 的话,那么对于这个分享的目录来说,他就具有 root 的权限 # 4、重启nfs、设置开机自启、检查 [root@master 10]# exportfs -arv [root@master 10]# service nfs restart # 不重启也可以,不影响 [root@master 10]# systemctl enable nfs [root@master 10]# systemctl status nfs ● nfs-server.service - NFS server and services Loaded: loaded (/usr/lib/systemd/system/nfs-server.service; enabled; vendor preset: disabled) Drop-In: /run/systemd/generator/nfs-server.service.d └─order-with-mounts.conf Active: active (exited) since Sun 2023-12-10 20:56:24 CST; 13s ago Main PID: 29331 (code=exited, status=0/SUCCESS) CGroup: /system.slice/nfs-server.service# 工作节点安装nfs驱动 [root@node01 ~]# yum install nfs-utils -y [root@node02 ~]# yum install nfs-utils -y [root@node01 ~]# systemctl enable nfs --now [root@node02 ~]# systemctl enable nfs --now # 测试nfs是否可以被正常挂载 [root@node01 ~]# mkdir /test [root@node01 ~]# mount 10.32.1.147:/data/volumes /test/ [root@node01 ~]# df -h|grep 147 10.32.1.147:/data/volumes 200G 50G 150G 26% /test # 手动卸载 [root@node01 ~]# umount /test4.2、挂载nfs共享目录Pod挂载nfs的官方地址:https://kubernetes.io/zh/docs/concepts/storage/volumes/# 1、创建pod,挂载nfs共享出来的目录 [root@master 10]# cat nfs.yaml apiVersion: apps/v1 kind: Deployment metadata: name: nfs-test spec: replicas: 3 selector: matchLabels: cunchu: nfs template: metadata: labels: cunchu: nfs spec: containers: - name: test-nfs image: xianchao/nginx:v1 # 这里的镜像根据实际情况替换 imagePullPolicy: IfNotPresent ports: - containerPort: 80 protocol: TCP volumeMounts: - name: nfs-volumes mountPath: /usr/share/nginx/html volumes: - name: nfs-volumes nfs: server: 10.32.1.147 # 提供nfs服务的主机ip,我这里就是控制节点master的ip path: /data/volumes # nfs的共享目录 [root@master 10]# kubectl apply -f nfs.yaml [root@master 10]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nfs-test-64466f5c4-gm52s 1/1 Running 0 61s 10.244.196.141 node01 <none> <none> nfs-test-64466f5c4-pcqsh 1/1 Running 0 63s 10.244.140.86 node02 <none> <none> nfs-test-64466f5c4-vp85f 1/1 Running 0 59s 10.244.140.87 node02 <none> <none># 2、登录到nfs服务器,在共享目录创建一个index.html [root@master ~]# cd /data/volumes [root@master volumes]# vim index.html [root@master volumes]# cat index.html Hello, Everyone My name is hejin My Chat is hj68223 # 3、进入其中一个容器,查看是否存在这个文件 [root@master volumes]# kubectl exec -it nfs-test-64466f5c4-gm52s /bin/bash kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead. root@nfs-test-64466f5c4-gm52s:/# cd /usr/share/nginx/html root@nfs-test-64466f5c4-gm52s:/usr/share/nginx/html# ls index.html # 4、请求pod的ip,看结果 [root@master 10]# curl 10.244.196.141 Hello, Everyone My name is hejin My Chat is hj68223 # 通过上面可以看到,在共享目录创建的index.html已经被pod挂载了上面说明挂载nfs存储卷成功了,nfs支持多个客户端挂载,可以创建多个pod,挂载同一个nfs服务器共享出来的目录;但是nfs如果宕机了,数据也就丢失了,所以需要使用分布式存储,常见的分布式存储有glusterfs和cephfs。五、k8s持久化存储: PVC参考官网:https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes5.1、什么是PVPersistentVolume(PV)是群集中的一块存储,由管理员配置或使用存储类动态配置。它是集群中的资源,就像pod是k8s集群资源一样。PV是容量插件,如Volumes,其生命周期独立于使用PV的任何单个pod。5.2、什么是PVCPersistentVolumeClaim(PVC)是一个持久化存储卷,我们在创建pod时可以定义这个类型的存储卷。它类似于一个pod。 Pod消耗节点资源,PVC消耗PV资源。Pod可以请求特定级别的资源(CPU和内存)。pvc在申请pv的时候也可以请求特定的大小和访问模式(例如,可以一次读写或多次只读)。5.3、PV和PVC工作原理PV是群集中的资源。 PVC是对这些资源的请求。PV和PVC之间的相互作用遵循以下生命周期:【1】pv供应方式可以通过两种方式配置PV:静态或动态。静态的:集群管理员创建了许多PV。它们包含可供群集用户使用的实际存储的详细信息。它们存在于Kubernetes API中,可供使用。动态的:当管理员创建的静态PV都不匹配用户的PersistentVolumeClaim时,群集可能会尝试为PVC专门动态配置卷。此配置基于StorageClasses,PVC必须请求存储类,管理员必须创建并配置该类,以便进行动态配置。【2】绑定用户创建pvc并指定需要的资源和访问模式。在找到可用pv之前,pvc会保持未绑定状态【3】使用a)需要找一个存储服务器,把它划分成多个存储空间;b)k8s管理员可以把这些存储空间定义成多个pv;c)在pod中使用pvc类型的存储卷之前需要先创建pvc,通过定义需要使用的pv的大小和对应的访问模式,找到合适的pv;d)pvc被创建之后,就可以当成存储卷来使用了,我们在定义pod时就可以使用这个pvc的存储卷e)pvc和pv它们是一一对应的关系,pv如果被pvc绑定了,就不能被其他pvc使用了;f)我们在创建pvc的时候,应该确保和底下的pv能绑定,如果没有合适的pv,那么pvc就会处于pending状态。【4】回收策略回收策略:persistentVolumeReclaimPolicy字段当我们创建pod时如果使用pvc做为存储卷,那么它会和pv绑定,当删除pod,pvc和pv绑定就会解除解除之后和pvc绑定的pv卷里的数据需要怎么处理,目前,卷可以保留,回收或删除:RetainRecycle (不推荐使用,1.15可能被废弃了)Delete1、Retain当删除pvc的时候,pv仍然存在,处于released状态,但是它不能被其他pvc绑定使用,里面的数据还是存在的,当我们下次再使用的时候,数据还是存在的,这个是默认的回收策略2、Delete删除pvc时即会从Kubernetes中移除PV,也会从相关的外部设施中删除存储资产5.4、使用pvc作为持久化存储卷创建pod,使用pvc作为持久化存储卷【1】创建nfs共享目录# 1、在宿主机创建NFS需要的共享目录 [root@master 10]# mkdir cd v{1,2,3,4,5,6,7,8,9,10} -p [root@master volumes]# cd /data/volume_test/ [root@master volume_test]# ls v1 v10 v2 v3 v4 v5 v6 v7 v8 v9 # 2、配置nfs共享宿主机上的/data/volume_test/v1..v10目录 [root@master 10]# cat /etc/exports /data/volumes *(rw,no_root_squash) /data/volume_test/v1 *(rw,no_root_squash) /data/volume_test/v2 *(rw,no_root_squash) /data/volume_test/v3 *(rw,no_root_squash) /data/volume_test/v4 *(rw,no_root_squash) /data/volume_test/v5 *(rw,no_root_squash) /data/volume_test/v6 *(rw,no_root_squash) /data/volume_test/v7 *(rw,no_root_squash) /data/volume_test/v8 *(rw,no_root_squash) /data/volume_test/v9 *(rw,no_root_squash) /data/volume_test/v10 *(rw,no_root_squash) # 重新加载配置,使配置成效 [root@master 10]# exportfs -arv【2】创建PV参考:https://kubernetes.io/zh/docs/concepts/storage/persistent-volumes/#reclaiming[root@master 10]# cat pv.yaml apiVersion: v1 kind: PersistentVolume metadata: name: v1 labels: app: v1 spec: nfs: server: 10.32.1.147 path: /data/volume_test/v1 accessModes: ["ReadWriteOnce"] # 访问模式 RWO capacity: storage: 1Gi # 设置存储容量 --- apiVersion: v1 kind: PersistentVolume metadata: name: v2 labels: app: v2 spec: nfs: server: 10.32.1.147 path: /data/volume_test/v2 accessModes: ["ReadOnlyMany"] # 访问模式 ROX capacity: storage: 2Gi --- apiVersion: v1 kind: PersistentVolume metadata: name: v3 labels: app: v3 spec: nfs: server: 10.32.1.147 path: /data/volume_test/v3 accessModes: ["ReadWriteMany"] # 访问模式 RWX capacity: storage: 3Gi [root@master 10]# kubectl apply -f pv.yaml persistentvolume/v1 created persistentvolume/v2 created persistentvolume/v3 created [root@master 10]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE v1 1Gi RWO Retain Available 26s v2 2Gi ROX Retain Available 26s v3 3Gi RWX Retain Available 26s注解:RWO:readwariteonce: 单路读写,允许同一个node节点上的pod访问ROX: readonlymany: 多路只读,允许不同node节点的pod以只读方式访问RWX: readwritemany: 多路读写,允许不同的node节点的pod以读写方式访问【3】创建PVC创建pvc,和符合条件的pv绑定[root@master 10]# cat pvc.yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-v1 spec: accessModes: ["ReadWriteOnce"] selector: matchLabels: app: v1 resources: requests: storage: 1Gi --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-v2 spec: accessModes: ["ReadOnlyMany"] selector: matchLabels: app: v2 resources: requests: storage: 2Gi --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-v3 spec: accessModes: ["ReadWriteMany"] selector: matchLabels: app: v3 resources: requests: storage: 3Gi [root@master 10]# kubectl apply -f pvc.yaml persistentvolumeclaim/pvc-v1 created persistentvolumeclaim/pvc-v2 created persistentvolumeclaim/pvc-v3 created [root@master 10]# kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE pvc-v1 Bound v1 1Gi RWO 57s pvc-v2 Bound v2 2Gi ROX 57s pvc-v3 Bound v3 3Gi RWX 57s # 看到pvc的status都是bound状态,就说明pvc跟pv已经绑定了【4】创建pod,挂载PVC[root@master 10]# cat pod_pvc.yaml apiVersion: apps/v1 kind: Deployment metadata: name: pvc-test spec: replicas: 3 selector: matchLabels: cunchu: pvc template: metadata: labels: cunchu: pvc spec: containers: - name: test-pvc image: docker.io/library/nginx:latest # 根据自己请情况替换镜像 imagePullPolicy: IfNotPresent ports: - containerPort: 80 protocol: TCP volumeMounts: - name: nginx-html mountPath: /usr/share/nginx/html volumes: - persistentVolumeClaim: claimName: pvc-v1 name: nginx-html [root@master 10]# kubectl apply -f pod_pvc.yaml [root@master 10]# kubectl get pod|grep pvc pvc-test-64bfccc668-bq529 1/1 Running 0 39s pvc-test-64bfccc668-bxjqx 1/1 Running 0 39s pvc-test-64bfccc668-t8xjt 1/1 Running 0 39s # 验证是否挂载成功 [root@master 10]# cd /data/volume_test/v1 [root@master v1]# ls [root@master v1]# mkdir lucky [root@master v1]# kubectl exec -it pvc-test-64bfccc668-bq529 /bin/bash kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead. root@pvc-test-64bfccc668-bq529:/# cd /usr/share/nginx/html/ root@pvc-test-64bfccc668-bq529:/usr/share/nginx/html# ls lucky注:使用pvc和pv的注意事项1、我们每次创建pvc的时候,需要事先有划分好的pv,这样可能不方便,那么可以在创建pvc的时候直接动态创建一个pv这个存储类,pv事先是不存在的2、pvc和pv绑定,如果使用默认的回收策略retain,那么删除pvc之后,pv会处于released状态,我们想要继续使用这个pv,需要手动删除pv,kubectl delete pv pv_name,删除pv,不会删除pv里的数据,当我们重新创建pvc时还会和这个最匹配的pv绑定,数据还是原来数据,不会丢失。经过测试,如果回收策略是Delete,删除pv,pv后端存储的数据也不会被删除删除pvc的步骤:1、需要先删除使用pvc的pod[root@master 10]# kubectl delete -f pod_pvc.yaml deployment.apps "pvc-test" deleted2、再删除pvc[root@master 10]# kubectl delete pvc pvc-v1 pvc-v2 pvc-v3 [root@master 10]# kubectl get pvc No resources found in default namespace. [root@master 10]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE v1 1Gi RWO Retain Released default/pvc-v1 41m v2 2Gi ROX Retain Released default/pvc-v2 41m v3 3Gi RWX Retain Released default/pvc-v3 41mpv状态变成Released ,就已经不能使用,需要删除,再重新创建后才能继续使用。但是共享目录下面的数据是不会被删除的,可以放心使用。演示pv用Delete回收策略1、创建pv[root@master 10]# cat pv-1.yaml apiVersion: v1 kind: PersistentVolume metadata: name: v4 labels: app: v4 spec: nfs: server: 10.32.1.147 path: /data/volume_test/v4 accessModes: ["ReadWriteOnce"] capacity: storage: 1Gi persistentVolumeReclaimPolicy: Delete [root@master 10]# kubectl apply -f pv-1.yaml2、创建pvc[root@master 10]# cat pvc-1.yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-v4 spec: accessModes: ["ReadWriteOnce"] selector: matchLabels: app: v4 resources: requests: storage: 1Gi [root@master 10]# kubectl apply -f pvc-1.yaml [root@master 10]# kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE pvc-v4 Bound v4 1Gi RWO 17s3、创建pod[root@master 10]# cat pod_pvc-2.yaml apiVersion: apps/v1 kind: Deployment metadata: name: pvc-test-1 spec: replicas: 3 selector: matchLabels: cunchu: pvc-1 template: metadata: labels: cunchu: pvc-1 spec: containers: - name: test-pvc image: docker.io/library/nginx:latest imagePullPolicy: IfNotPresent ports: - containerPort: 80 protocol: TCP volumeMounts: - name: nginx-html mountPath: /usr/share/nginx/html volumes: - persistentVolumeClaim: claimName: pvc-v4 name: nginx-html name: nginx-html [root@master 10]# kubectl apply -f pod_pvc-2.yaml [root@master 10]# kubectl get pod|grep pvc pvc-test-1-6f5d6d8699-5mbn6 1/1 Running 0 27s pvc-test-1-6f5d6d8699-gjv4s 1/1 Running 0 27s pvc-test-1-6f5d6d8699-xh4c9 1/1 Running 0 27s4、验证是否共享存储卷 [root@master v4]# cd /data/volume_test/v4 [root@master v4]# ll total 0 [root@master v4]# mkdir lucky [root@master v4]# ll total 0 drwxr-xr-x. 2 root root 6 Dec 10 22:46 lucky [root@master 10]# kubectl exec -it pvc-test-1-6f5d6d8699-5mbn6 -- /bin/bash root@pvc-test-1-6f5d6d8699-5mbn6:/# cd /usr/share/nginx/html/ root@pvc-test-1-6f5d6d8699-5mbn6:/usr/share/nginx/html# ls lucky[root@master 10]# kubectl delete -f pod_pvc-2.yaml [root@master 10]# kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE pvc-v4 Bound v4 1Gi RWO 17m [root@master 10]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE v4 1Gi RWO Delete Bound default/pvc-v4 11m [root@master 10]# kubectl delete pvc pvc-v4 [root@master 10]# kubectl get pv|grep v4 # 此处有问题,pv的状态为Failed ,所以共享目录中数据没有被删除,后续有空再排查原因...... v4 1Gi RWO Delete Failed default/pvc-v4 19m当与该PV相关联的PVC(Persistent Volume Claim)被删除时,PV上的数据将被自动删除。换句话说,一旦没有任何PVC使用这个PV,Kubernetes将自动删除PV中的数据以及PV本身。这种行为确保了资源的及时释放,以及在没有使用的PV上不会保留不必要的数据。因此,在设置PV时,需要根据实际需求谨慎选择适当的删除策略,以确保数据和资源的合理管理。
0
0
0
浏览量2014
锅从天上来

K8S(六)—kubectl

Kubectlkubectl 是 Kubernetes 命令行工具,用于与 Kubernetes 集群进行交互、管理资源、执行操作以及获取有关集群和应用程序的信息。以下是一些常用的 kubectl 命令及其详细介绍:1.基本信息和状态查询命令:kubectl version:显示 Kubernetes 客户端和服务器的版本信息。kubectl cluster-info:显示集群的基本信息,如控制平面的地址和端口。kubectl get nodes:获取集群中的节点列表。kubectl get pods:获取所有命名空间中的 Pod 列表。kubectl get services:获取所有命名空间中的服务列表。2.资源管理命令:kubectl create:创建资源对象,如 Pod、Service、Deployment 等。kubectl apply:将配置文件中的资源对象应用到集群。kubectl delete:删除资源对象。kubectl scale:调整副本数。kubectl expose:将 Deployment 或 Replication Controller 暴露为 Service。3.资源查询和描述命令:kubectl describe:显示资源对象的详细信息,如 Pod、Service、Node 等。kubectl logs:查看容器的日志。kubectl get events:获取事件列表,显示有关集群中发生的事件的信息。4.应用程序管理命令:kubectl exec:在容器中执行命令。kubectl port-forward:将本地端口与容器端口进行转发。kubectl run:创建一个 Pod。5.命名空间命令:kubectl create namespace:创建命名空间。kubectl get namespaces:获取命名空间列表。6.配置和上下文命令:kubectl config use-context:切换到不同的集群和上下文。kubectl config current-context:显示当前上下文。kubectl config view:查看和管理配置文件。7.升级和回滚命令:kubectl rollout status:监控 Deployment、DaemonSet 或 StatefulSet 升级的状态。kubectl rollout history:查看资源对象的版本历史。kubectl rollout undo:回滚到以前的版本。8.插件和其他命令:kubectl plugin:管理 kubectl 插件。kubectl apply -f:应用配置文件。kubectl get -o yaml:获取资源对象的 YAML 格式配置。以上只是一些常用的 kubectl 命令,Kubernetes 提供了更多功能丰富的命令用于集群管理和应用程序部署。您可以通过运行 kubectl --help 查看完整的命令列表以及每个命令的选项和说明。deletekubectl delete 是 Kubernetes 命令行工具中的一个子命令,用于从 Kubernetes 集群中删除资源对象。使用 kubectl delete 命令可以删除 Pod、Deployment、Service、Namespace 等各种 Kubernetes 资源。以下是 kubectl delete 命令的详细介绍:基本用法:kubectl delete RESOURCE_TYPE RESOURCE_NAMERESOURCE_TYPE: 要删除的资源类型,如 pod、deployment、service 等。RESOURCE_NAME: 要删除的资源对象的名称。删除指定命名空间中的资源:可以使用 -n 或 --namespace 参数指定要删除资源所在的命名空间。如果不指定命名空间,则默认为当前命名空间。kubectl delete RESOURCE_TYPE RESOURCE_NAME -n NAMESPACE删除所有资源:如果要删除一个命名空间中的所有资源,可以使用 --all 参数。kubectl delete RESOURCE_TYPE --all -n NAMESPACE强制删除:默认情况下,kubectl delete 命令将会尝试优雅地删除资源,即先发送一个删除信号给资源对象,然后等待资源对象自行终止。如果资源对象没有正确终止,可以添加 --grace-period=0 参数来立即删除资源。kubectl delete RESOURCE_TYPE RESOURCE_NAME --grace-period=0删除符合条件的资源:可以使用 --selector 参数删除符合特定标签选择器的资源。kubectl delete RESOURCE_TYPE --selector=LABEL_SELECTOR删除指定文件中定义的资源:可以使用 -f 或 --filename 参数指定一个 YAML 或 JSON 文件,其中定义了要删除的资源对象的信息。kubectl delete -f FILENAME常见的 RESOURCE_TYPE 类型:以下是一些常见的 RESOURCE_TYPE 类型:pod: 删除一个或多个 Pod。deployment: 删除一个或多个 Deployment。service: 删除一个或多个 Service。namespace: 删除一个命名空间及其所有资源。configmap: 删除一个或多个 ConfigMap。secret: 删除一个或多个 Secret。ingress: 删除一个或多个 Ingress。请注意,在使用 kubectl delete 命令时,请谨慎操作,以免意外删除重要的资源。确保在删除前确认您要删除的资源和命名空间。kubectl delete pod k8s-nginx2-7d9f66c959-j2dqw删除其中一个,查看是否自动启动其他容器填充[root@k8smaster1 ~]# kubectl get rs NAME DESIRED CURRENT READY AGE k8s-nginx-75f95db655 3 3 1 20m k8s-nginx2-7d9f66c959 3 3 3 8m11s [root@k8smaster1 ~]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES ... k8s-nginx2-7d9f66c959-sqglm 1/1 Running 0 8m18s 10.244.185.198 k8snode2 <none> <none> k8s-nginx2-7d9f66c959-v5gfm 1/1 Running 0 32s 10.244.185.199 k8snode2 <none> <none> k8s-nginx2-7d9f66c959-xnjv7 1/1 Running 0 8m18s 10.244.185.196 k8snode2 <none> <none>getexplainkubectl explain 是一个用于查看 Kubernetes 资源对象及其字段的详细说明的命令。它可以帮助您了解 Kubernetes API 中每个资源类型的属性和配置选项。以下是对 kubectl explain 命令的详细解析:命令格式:kubectl explain <资源类型> [选项]参数说明:<资源类型>:指定要查看的资源类型,如 pod、deployment、service 等。[选项]:可选参数,用于指定要查看的属性或字段。使用示例:1.查看资源类型的基本信息:kubectl explain <资源类型>2.查看资源类型的某个字段的详细信息:kubectl explain <资源类型>.<字段>3.查看嵌套字段的详细信息:kubectl explain <资源类型>.<嵌套字段>.<子嵌套字段>示例解释:假设您想要了解 Pod 的 spec 字段的详细信息,可以执行以下命令:kubectl explain pod.spec这将显示 Pod 资源类型的 spec 字段的详细信息,包括该字段的类型、描述、可能的值范围等。如果您想要查看嵌套字段,例如查看 Pod 的 spec.containers 字段的详细信息,可以执行以下命令:kubectl explain pod.spec.containers这将显示 Pod 资源类型中的 spec 字段的 containers 字段的详细信息,以及它包含的属性和值的描述。通过使用 kubectl explain 命令,您可以在命令行中方便地查看 Kubernetes 资源对象的详细说明,从而更好地了解如何配置和使用这些资源。这对于编写和管理 Kubernetes 配置文件以及进行资源操作非常有帮助。[root@k8smaster ~]# kubectl explain ResourceQuota[root@k8smaster ~]# kubectl explain ResourceQuota.metadataapplykubectl apply 是用于将 Kubernetes 资源配置应用到集群中的命令。它可以用来创建、更新或删除资源,并且支持声明式配置,使得您可以通过修改配置文件来管理资源状态。以下是对 kubectl apply 命令的详细解析:命令格式:kubectl apply -f <配置文件> [选项]参数说明:-f <配置文件>:指定要应用的资源配置文件,可以是 YAML 或 JSON 格式。[选项]:可选参数,用于指定命名空间、输出格式等。使用示例:1.创建或更新资源:kubectl apply -f <配置文件>2.删除资源:kubectl delete -f <配置文件>特点和功能:声明式配置:kubectl apply 支持声明式配置,即您可以通过修改配置文件来定义所需的资源状态,而不必手动执行多个命令来达到目标状态。幂等性:kubectl apply 是幂等的,这意味着无论您执行多少次相同的应用操作,最终结果都会是一样的,而不会引起冲突或错误。创建与更新:如果资源不存在,kubectl apply 会创建它;如果资源已存在,但与配置文件不匹配,它会更新资源的配置以符合文件中的定义。局部更新:kubectl apply 可以部分更新资源,只更新配置文件中指定的字段,而不影响其他字段的值。命名空间支持:您可以通过 -n 或 --namespace 选项指定要应用资源的命名空间。多文件应用:您可以一次性应用多个配置文件,kubectl apply -f <文件1> -f <文件2>。输出格式:可以使用 --dry-run、-o 或 --output 选项指定输出的格式,如 json、yaml 等。使用示例解释:假设您有一个名为 deployment.yaml 的配置文件,其中定义了一个 Deployment 资源。通过以下命令,您可以将此配置文件中定义的 Deployment 应用到集群中:kubectl apply -f deployment.yaml如果此 Deployment 已存在,但是配置文件中的定义与现有资源不同,kubectl apply 将会更新现有的 Deployment 以匹配配置文件中的定义。
0
0
0
浏览量2011
锅从天上来

【Kubernetes】认证授权RBAC (二)

一、资源引用方式1.1、通过资源名称的字符串引用多数资源可以用其名称的字符串表示,也就是Endpoint中的URL相对路径例如pod中的日志是GET /api/v1/namaspaces/{namespace}/pods/{podname}/log如果需要在一个RBAC对象中体现上下级资源,就需要使用“/”分割资源和下级资源。例如:若想授权让某个主体同时能够读取Pod和Pod log,则可以配置 resources为一个数组。【1】创建role,与sa绑定在test空间下,创建logs-reader的role,赋予对Pod和Pod log的读取权限。并将其与test空间下的sa-test这个sa进行绑定。[root@master 16]# kubectl create ns test namespace/test created [root@master 16]# vim role-test.yaml [root@master 16]# cat role-test.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: logs-reader namespace: test rules: - apiGroups: [""] resources: ["pods","pods/log"] verbs: ["get","list","watch"] [root@master 16]# kubectl apply -f role-test.yaml role.rbac.authorization.k8s.io/logs-reader created [root@master 16]# kubectl create sa sa-test -n test serviceaccount/sa-test created [root@master 16]# kubectl create rolebinding sa-test-1 -n test --role=logs-reader --serviceaccount=test:sa-test rolebinding.rbac.authorization.k8s.io/sa-test-1 created [root@master 16]# kubectl get role -n test NAME CREATED AT logs-reader 2024-01-06T14:22:26Z【2】创建pod,与sa关联在test空间下,创建sa-test-pod的pod。并将其与test空间下的sa-test这个sa进行关联。[root@master 16]# vim pod-test.yaml [root@master 16]# cat pod-test.yaml apiVersion: v1 kind: Pod metadata: name: sa-test-pod namespace: test labels: app: sa spec: serviceAccountName: sa-test containers: - name: sa-tomcat ports: - containerPort: 80 image: nginx imagePullPolicy: IfNotPresent [root@master 16]# kubectl apply -f pod-test.yaml pod/sa-test-pod created [root@master 16]# kubectl get pod -n test NAME READY STATUS RESTARTS AGE sa-test-pod 1/1 Running 0 26s【3】验证[root@master 16]# kubectl exec -it sa-test-pod -n test -- /bin/bash root@sa-test-pod:/# root@sa-test-pod:/# cd /var/run/secrets/kubernetes.io/serviceaccount # 该pod对默认ns下的资源是没有访问权限的 root@sa-test-pod:/var/run/secrets/kubernetes.io/serviceaccount# curl --cacert ./ca.crt -H "Authorization: Bearer $(cat ./token)" https://kubernetes.default/api/v1/namespaces/default/pods/read-pod/log { "kind": "Status", "apiVersion": "v1", "metadata": {}, "status": "Failure", "message": "pods \"read-pod\" is forbidden: User \"system:serviceaccount:test:sa-test\" cannot get resource \"pods/log\" in API group \"\" in the namespace \"default\"", "reason": "Forbidden", "details": { "name": "read-pod", "kind": "pods" }, "code": 403 }root@sa-test-pod:/var/run/secrets/kubernetes.io/serviceaccount## 验证对test空间的pod是否有访问权限 }root@sa-test-pod:/var/run/secrets/kubernetes.io/serviceaccount# curl --cacert ./ca.crt -H "Authorization: Bearer $(cat ./token)" https://kubernetesdefault/api/v1/namespaces/test/pods ...... # 验证对test空间的pod的log是否有访问权限 }root@sa-test-pod:/var/run/secrets/kubernetes.io/serviceaccount# curl --cacert ./ca.crt -H "Authorization: Bearer $(cat ./token)" https://kubernetesdefault/api/v1/namespaces/test/pods/sa-test-pod/log { "kind": "Status", "apiVersion": "v1", "metadata": {}, "status": "Failure", "message": "pods \"sa-test-pod\" is forbidden: User \"system:serviceaccount:test:sa-test\" cannot get resource \"pods/logs\" in API group \"\" in the namespace \"test\"", "reason": "Forbidden", "details": { "name": "sa-test-pod", "kind": "pods" }, "code": 403 }root@sa-test-pod:/var/run/secrets/kubernetes.io/serviceaccount#以上报错:pods \"sa-test-pod\" is forbidden: User \"system:serviceaccount:test:sa-test\" cannot get resource \"pods/logs\" in API group \"\" in the namespace \"test\"原因:system:serviceaccount:test:sa-test这个系统用户不能获取pod资源解决:[root@master 16]# kubectl create rolebinding sa-test-2 -n test --role=logs-reader --user=system:serviceaccount:test:sa-test rolebinding.rbac.authorization.k8s.io/sa-test-2 createdroot@sa-test-pod:/var/run/secrets/kubernetes.io/serviceaccount# curl --cacert ./ca.crt -H "Authorization: Bearer $(cat ./token)" https://kubernetesdefault/api/v1/namespaces/test/pods/sa-test-pod/log /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/ /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf 10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf /docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh /docker-entrypoint.sh: Configuration complete; ready for start up 2024/01/06 14:28:03 [notice] 1#1: using the "epoll" event method 2024/01/06 14:28:03 [notice] 1#1: nginx/1.25.3 2024/01/06 14:28:03 [notice] 1#1: built by gcc 12.2.0 (Debian 12.2.0-14) 2024/01/06 14:28:03 [notice] 1#1: OS: Linux 3.10.0-1160.92.1.el7.x86_64 2024/01/06 14:28:03 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576 2024/01/06 14:28:03 [notice] 1#1: start worker processes 2024/01/06 14:28:03 [notice] 1#1: start worker process 29 2024/01/06 14:28:03 [notice] 1#1: start worker process 30 2024/01/06 14:28:03 [notice] 1#1: start worker process 31 2024/01/06 14:28:03 [notice] 1#1: start worker process 321.2、通过名称(ResourceName)引用在指定ResourceName后,使用get、delete、update、patch请求,就会被限制在这个资源实例范围内例如,下面的声明让一个主体只能对名为my-configmap的Configmap进行get和update操作:apiVersion: rabc.authorization.k8s.io/v1 kind: Role metadata: namaspace: default name: configmap-update rules: - apiGroups: [""] resources: ["configmaps"] resourceNames: ["my-configmap"] verbs: ["get","update"]二、常见案例2.1、常见角色(role)授权的案例【1】允许读取核心API组的Pod资源rules: - apiGroups: [""] resources: ["pods"] verbs: ["get","list","watch"]【2】允许读写apps API组中的deployment资源rules: - apiGroups: ["apps"] resources: ["deployments"] verbs: ["get","list","watch","create","update","patch","delete"]【3】允许读取Pod以及读写job信息rules: - apiGroups: [""] resources: ["pods"] verbs: ["get","list","watch"] - apiGroups: [""] resources: ["jobs"] verbs: ["get","list","watch","create","update","patch","delete"]【4】允许读取一个名为my-config的ConfigMap(必须绑定到一个RoleBinding来限制到一个Namespace下的ConfigMap):rules: - apiGroups: [""] resources: ["configmaps"] resourceNames: ["my-configmap"] verbs: ["get"]【5】读取核心组的Node资源(Node属于集群级的资源,所以必须存在于ClusterRole中,并使用ClusterRoleBinding进行绑定):rules: - apiGroups: [""] resources: ["nodes"] verbs: ["get","list","watch"]【6】允许对非资源端点“/healthz”及其所有子路径进行GET和POST操作必须使用ClusterRole和ClusterRoleBinding):rules: - nonResourceURLs: ["/healthz","/healthz/*"] verbs: ["get","post"]2.2、常见的sa授权案例(1)my-namespace中的my-sa Service Account授予只读权限kubectl create rolebinding my-sa-view --clusterrole=view --serviceaccount=my-namespace:my-sa --namespace=my-namespace(2)为一个命名空间中名为default的Service Account授权如果一个应用没有指定 serviceAccountName,则会使用名为default的Service Account。注意,赋予Service Account “default”的权限会让所有没有指定serviceAccountName的Pod都具有这些权限例如,在my-namespace命名空间中为Service Account“default”授予只读权限:kubectl create rolebinding default-view --clusterrole=view --serviceaccount=my-namespace:default --namespace=my-namespace(3)为命名空间中所有Service Account都授予一个角色如果希望在一个命名空间中,任何Service Account应用都具有一个角色,则可以为这一命名空间的Service Account群组进行授权kubectl create rolebinding serviceaccounts-view --clusterrole=view --group=system:serviceaccounts:my-namespace --namespace=my-namespace(4)为集群范围内所有Service Account都授予一个低权限角色如果不想为每个命名空间管理授权,则可以把一个集群级别的角色赋给所有Service Account。kubectl create clusterrolebinding serviceaccounts-view --clusterrole=view --group=system:serviceaccounts(5)为所有Service Account授予超级用户权限kubectl create clusterrolebinding serviceaccounts-view --clusterrole=cluster-admin --group=system:serviceaccounts2.3、常见的角色绑定的案例(1)在命名空间rbac中为用户es授权admin ClusterRole:kubectl create rolebinding bob-admin-binding --clusterrole=admin --user=es --namespace=rbac(2)在命名空间rbac中为名为myapp的Service Account授予view ClusterRole:kubctl create rolebinding myapp-role-binding --clusterrole=view --serviceaccount=rbac:myapp --namespace=rbac(3)在全集群范围内为用户root授予cluster-admin ClusterRole:kubectl create clusterrolebinding cluster-binding --clusterrole=cluster-admin --user=root(4)在全集群范围内为名为myapp的Service Account授予view ClusterRole:kubectl create clusterrolebinding service-account-binding --clusterrole=view --serviceaccount=myappyaml文件进行rbac授权:https://kubernetes.io/zh/docs/reference/access-authn-authz/rbac/三、限制不同的用户操作k8s集群3.1、限制用户只对特定ns有管理员权限【1】生成证书[root@master ~]# cd /etc/kubernetes/pki/ # 1、生成私钥 [root@master pki]# (umask 077; openssl genrsa -out lucky.key 2048) Generating RSA private key, 2048 bit long modulus .........+++ .........................................................+++ e is 65537 (0x10001) # 2、生成证书请求文件 [root@master pki]# openssl req -new -key lucky.key -out lucky.csr -subj "/CN=lucky" # 3、生成证书 [root@master pki]# openssl x509 -req -in lucky.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out lucky.crt -days 3650 Signature ok subject=/CN=lucky Getting CA Private Key【2】新增lucky用户(1)把lucky这个用户添加到kubernetes集群中,可以用来认证apiserver的连接[root@master pki]# kubectl config set-credentials lucky --client-certificate=./lucky.crt --client-key=./lucky.key --embed-certs=true User "lucky" set.(2)在kubeconfig下新增加一个lucky这个账号[root@master pki]# kubectl config set-context lucky@kubernetes --cluster=kubernetes --user=lucky Context "lucky@kubernetes" created.(3)切换账号到lucky,默认没有任何权限kubectl config use-context lucky@kubernetes kubectl config use-context kubernetes-admin@kubernetes 这个是集群用户,有任何权限[root@master pki]# kubectl config use-context lucky@kubernetes Switched to context "lucky@kubernetes". [root@master pki]# kubectl get pod Error from server (Forbidden): pods is forbidden: User "lucky" cannot list resource "pods" in API group "" in the namespace "default"把lucky这个用户通过rolebinding绑定到clusterrole上,授予权限,权限只是在lucky这个名称空间有效【3】lucky用户绑定到名为cluster-admin的clusterrole[root@master pki]# kubectl create ns lucky-test namespace/lucky-test created # 把lucky这个用户通过rolebinding绑定到clusterrole上 [root@master pki]# kubectl create rolebinding lucky -n lucky-test --clusterrole=cluster-admin --user=lucky rolebinding.rbac.authorization.k8s.io/lucky created # 切换到lucky这个用户 [root@master pki]# kubectl config use-context lucky@kubernetes Switched to context "lucky@kubernetes". # 测试是否有权限 [root@master pki]# kubectl get pods -n lucky-test No resources found in lucky-test namespace. # 有权限操作这个名称空间 [root@master pki]# kubectl create sa aa -n lucky-test serviceaccount/aa created [root@master pki]# kubectl get sa -n lucky-test NAME SECRETS AGE aa 0 27s default 0 6m24s【4】添加一个test的普通用户将自己集群的k8s配置文件拷贝到/tmp下,不一定是/root/.kube/config,也有可能是/etc/kubernetes/admin.conf。使用echo $KUBECONFIG 查看[root@master pki]# useradd test [root@master pki]# cp -ar /root/.kube /tmp/ # 修改/tmp/.kube/config文件,把kubernetes-admin相关的删除,只留lucky用户 # 将修改好的文件cp到test用户指定的配置文件路径下 [root@master pki]# cp -ar /tmp/.kube /home/test/.kube [root@master .kube]# pwd /home/test/.kube [root@master .kube]# chown -R test:test /home/test/ [root@master .kube]# passwd test Changing password for user test. New password: BAD PASSWORD: The password is shorter than 8 characters Retype new password: passwd: all authentication tokens updated successfully.test用户登录,查看权限。如何查看不了,可以指定–kubeconfig=/home/test/kubernetes/admin.conf。因为我这里的配置文件不是~/.kube/config[test@master ~]$ kubectl get pod --kubeconfig=/home/test/kubernetes/admin.conf Error from server (Forbidden): pods is forbidden: User "lucky" cannot list resource "pods" in API group "" in the namespace "default" [test@master ~]$ kubectl get pod -n lucky-test --kubeconfig=/home/test/kubernetes/admin.conf No resources found in lucky-test namespace.3.2、授权用户对所有ns的pod查看权限【1】生成证书[root@master test]# cd /etc/kubernetes/pki/ # 1、生成一个私钥 [root@master pki]# (umask 077; openssl genrsa -out hejin.key 2048) Generating RSA private key, 2048 bit long modulus ....................................+++ ...............+++ e is 65537 (0x10001) # 2、生成一个请求证书 [root@master pki]# openssl req -new -key hejin.key -out hejin.csr -subj "/CN=hejin" # 3、生成一个证书 [root@master pki]# openssl x509 -req -in hejin.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out hejin.crt -days 3650 Signature ok subject=/CN=hejin Getting CA Private Key【2】新增hejin用户,创建clusterrole对所有pod有访问权限(1)把hejin这个用户添加到kubernetes集群中,可以用来认证apiserver的连接[root@master pki]# kubectl config set-credentials hejin --client-certificate=./hejin.crt --client-key=./hejin.key --embed-certs=true User "hejin" set.(2)在kubeconfig下新增加一个lucky这个账号[root@master pki]# kubectl config set-context hejin@kubernetes --cluster=kubernetes --user=hejin Context "hejin@kubernetes" created.(3)创建一个clusterrole[root@master 20240106]# cat hejin-clusterrole.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: hejin-get-pod rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "watch"] [root@master 20240106]# kubectl apply -f hejin-clusterrole.yaml clusterrole.rbac.authorization.k8s.io/hejin-get-pod created【3】hejin用户绑定到clusterrole[root@master 20240106]# kubectl get ClusterRole |grep hejin hejin-get-pod 2024-01-07T08:27:22Z # 通过clusterrolebinding 绑定可以访问所有ns下的pod资源 [root@master 20240106]# kubectl create clusterrolebinding hejin-get-pods --clusterrole=hejin-get-pod --user=hejin clusterrolebinding.rbac.authorization.k8s.io/hejin-get-pods created【4】添加一个test66的普通用户[root@master 20240106]# useradd test66 [root@master 20240106]# echo $KUBECONFIG /etc/kubernetes/admin.conf [root@master 20240106]# cp -ar /etc/kubernetes /home/test66/ [root@master 20240106]# chown -R test66:test66 /home/test66/ [root@master 20240106]# cd /home/test66/kubernetes [root@master kubernetes]# ll total 40 -rw-------. 1 root root 13007 Jan 7 16:19 admin.conf -rw-------. 1 root root 5671 Dec 6 10:46 controller-manager.conf -rw-------. 1 root root 1959 Dec 6 10:47 kubelet.conf drwxr-xr-x. 2 root root 113 Dec 11 11:03 manifests drwxr-xr-x. 3 root root 4096 Jan 7 16:15 pki -rw-------. 1 root root 5619 Dec 6 10:46 scheduler.conf [root@master kubernetes]# vim admin.conf把kubernetes-admin和lucky相关的删除,只留hejin用户修改后:[root@master kubernetes]# su - test66 [test66@master ~]$ kubectl get pods -n kube-system --kubeconfig=/home/test66/kubernetes/admin.conf NAME READY STATUS RESTARTS AGE calico-kube-controllers-6744f6b6d5-lpxpn 1/1 Running 0 2d2h calico-node-jlwwd 1/1 Running 0 18h calico-node-jvrr2 1/1 Running 0 18h calico-node-smw6v 1/1 Running 0 18h 2d2h ....... [test66@master ~]$ kubectl get pods --kubeconfig=/home/test66/kubernetes/admin.conf NAME READY STATUS RESTARTS AGE busybox-demo 1/1 Running 49 (54m ago) 2d1h front-end-5849b54454-29g9m 1/1 Running 0 47h front-end-5849b54454-qlvlq 1/1 Running 0 47h .......四 、准入控制4.1、ResourceQuota准入控制器ResourceQuota准入控制器是k8s上内置的,默认是启用状态。主要作用是用来限制一个ns下资源的使用,能防止在一个ns下的pod被过多创建时,导致过多占用k8s资源。简单来讲它是用来在名称空间级别显示用户的资源使用。【1】限制cpu、内存、pod、deployment数量[root@master 16]# kubectl create ns quota namespace/quota created [root@master 16]# cat resourcequota-1.yaml apiVersion: v1 kind: ResourceQuota metadata: name: quota-test namespace: quota spec: hard: # 定义对应名称空间下的资源限制规则 pods: "6" # 限制在对应名称空间下的pod数量 requests.cpu: "2" # 限制对应名称空间下所有pod的cpu资源的下限总和 requests.memory: 2Gi # 限制对应名称空间下pod的内存资源的下限总和 limits.cpu: "4" # 限制对应名称空间下的podcpu资源的上限总和 limits.memory: 10Gi # 限制对应名称空间下pod内存资源上限总和 count/deployments.apps: "6" # 限制对应名称空间下apps群组下的deployments的个数 persistentvolumeclaims: "6" # pvc限制 [root@master 16]# kubectl apply -f resourcequota-1.yaml resourcequota/quota-test created [root@master 16]# kubectl get ResourceQuota -n quota NAME AGE REQUEST LIMIT quota-test 5m55s count/deployments.apps: 1/6, persistentvolumeclaims: 0/6, pods: 6/6, requests.cpu: 60m/2, requests.memory: 60Mi/2Gi limits.cpu: 60m/4, limits.memory: 60Mi/10Gi以上配置清单表示,在quota名称空间下运行的pod数量不能超过6个,所有pod的cpu资源下限总和不能大于2个核心,内存资源下限总和不能大于2G,cpu上限资源总和不能大于4个核心,内存上限总和不能超过10G,apps群组下的deployments控制器不能超过6个, pvc个数不能超过6个;以上条件中任意一个条目不满足,都将无法在对应名称空间创建对应的资源。创建pod进行演示验证:[root@master 16]# cat quota-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: quota namespace: quota spec: replicas: 7 # 之前限制了最多只能创建6个pod,此处定义7个,看是否限制成功 selector: matchLabels: app: quota template: metadata: labels: app: quota spec: containers: - name: myapp image: janakiramm/myapp:v1 imagePullPolicy: IfNotPresent ports: - containerPort: 80 resources: requests: cpu: 10m memory: 10Mi # 如果这里定义成1Gi,那么最终只能创建2个pod,可自行测试 limits: cpu: 10m memory: 10Mi [root@master 16]# kubectl apply -f quota-deployment.yaml deployment.apps/quota created [root@master 16]# kubectl get pods -n quota -owide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES quota-6d5c459f69-5lg72 1/1 Running 0 62s 10.244.196.189 node01 <none> <none> quota-6d5c459f69-5zsz8 1/1 Running 0 62s 10.244.196.191 node01 <none> <none> quota-6d5c459f69-6xhmj 1/1 Running 0 62s 10.244.196.190 node01 <none> <none> quota-6d5c459f69-8jd4l 1/1 Running 0 62s 10.244.196.187 node01 <none> <none> quota-6d5c459f69-d76n4 1/1 Running 0 62s 10.244.196.132 node01 <none> <none> quota-6d5c459f69-qlssq 1/1 Running 0 62s 10.244.196.188 node01 <none> <none>查看资源使用情况[root@master 16]# kubectl get ResourceQuota -n quota NAME AGE REQUEST LIMIT quota-test 5m55s count/deployments.apps: 1/6, persistentvolumeclaims: 0/6, pods: 6/6, requests.cpu: 60m/2, requests.memory: 60Mi/2Gi limits.cpu: 60m/4, limits.memory: 60Mi/10Gi [root@master 16]# kubectl describe quota -n quota Name: quota-test Namespace: quota Resource Used Hard -------- ---- ---- count/deployments.apps 1 6 limits.cpu 60m 4 limits.memory 60Mi 10Gi persistentvolumeclaims 0 6 pods 6 6 requests.cpu 60m 2 requests.memory 60Mi 2Gi【2】限制存储空间大小[root@master 16]# cat resourcequota-2.yaml apiVersion: v1 kind: ResourceQuota metadata: name: quota-storage-test namespace: quota spec: hard: requests.storage: "5Gi" # 限制对应名称空间下的存储下限总和 persistentvolumeclaims: "5" # 限制pvc总数量 requests.ephemeral-storage: "1Gi" # 限制使用本地临时存储的下限总容量 limits.ephemeral-storage: "2Gi" # 限制使用本地临时存储上限总容量 [root@master 16]# kubectl apply -f resourcequota-2.yaml resourcequota/quota-storage-test created以上配置表示在default名称空间下非停止状态的容器存储下限总容量不能超过5G,pvc的数量不能超过5个,本地临时存储下限容量不能超过1G,上限不能超过2G。可自行创建pod测试4.2、LimitRanger准入控制器LimitRanger准入控制器也是k8s内置的,是k8s上的一个标准资源,主要用来定义在某个名称空间下限制pod和pod里容器对k8s上的cpu和内存资源使用。它能够定义我们在某个ns下创建pod时使用的cpu和内存上下限以及默认的cpu和内存上下限。如果我们创建pod时定义了资源上下限,但不满足LimitRange规则中定义的资源上下限,此时LimitRanger救护拒绝我们创建pod。如果LimitRanger规则中定义了默认的资源上下限,我们创建资源的时候没有指定资源限制,就会使用这个默认的同样的逻辑,LimitRanger可以限制一个pod使用资源的上下限,它还可以限制pod中的容器的资源上下限,比限制pod更加精准;不管是针对pod还是pod里的容器,它始终只是限制单个pod资源使用。[root@master 16]# cat limitrange.yaml apiVersion: v1 kind: Namespace metadata: name: limit --- apiVersion: v1 kind: LimitRange metadata: name: cpu-memory namespace: limit spec: limits: - default: # 指定默认容器资源上限值 cpu: 1000m memory: 1000Mi defaultRequest: # 指定默认容器资源下限值 cpu: 500m memory: 500Mi min: # 限制用户指定的资源下限不能小于对应资源的值 cpu: 500m memory: 500Mi max: # 限制用户指定资源上限值不能大于该值 cpu: 2000m memory: 2000Mi maxLimitRequestRatio: # 指定资源的上限和下限的比值,上限是下限的多少倍 cpu: 4 memory: 4 type: Container # 描述对应资源限制的级别,该字段有两个值pod和container。 [root@master 16]# kubectl apply -f limitrange.yaml namespace/limit created limitrange/cpu-memory created上述资源清单表示在该名称空间下创建pod时,默认不指定其容器的资源限制,就限制对应容器最少要有0.5个核心的cpu和500M的内存;最大为1个核心cpu,1g内存;如果我们手动定义了容器的资源限制,那么对应资源限制最小不能小于cpu为0.5个核心,内存为500M,最大不能超过cpu为2个核心,内存为2000M;如果我们在创建pod时,只指定了容器的资源上限或下限,那么上限最大是下限的的4倍,如果指定cpu上限为2000m那么下限一定不会小于500m,如果只指定了cpu下限为500m那么上限最大不会超过2000m,对于内存也是同样的逻辑。【1】在limit名称空间创建pod,不指定资源,看看是否会被limitrange规则自动附加其资源限制?[root@master 16]# vim pod-limit.yaml [root@master 16]# kubectl apply -f pod-limit.yaml pod/nginx-pod-demo created [root@master 16]# cat pod-limit.yaml apiVersion: v1 kind: Pod metadata: name: nginx-pod-demo namespace: limit spec: containers: - image: nginx imagePullPolicy: IfNotPresent name: nginx [root@master 16]# kubectl describe pods nginx-pod-demo -n limit通过上面结果可以看到我们在limit名称空间下创建的pod没有指定其容器资源限制,创建pod后,其内部容器自动就有了默认的资源限制;其大小就是我们在定义LimitRange规则中的default和defaultRequest字段中指定的资源限制。【2】创建pod,指定cpu请求是100m,看看是否允许创建[root@master 16]# vim pod-request.yaml [root@master 16]# cat pod-request.yaml apiVersion: v1 kind: Pod metadata: name: pod-request namespace: limit spec: containers: - image: nginx imagePullPolicy: IfNotPresent name: nginx resources: requests: cpu: 100m [root@master 16]# kubectl apply -f pod-request.yaml Error from server (Forbidden): error when creating "pod-request.yaml": pods "pod-request" is forbidden: [minimum cpu usage per Container is 500m, but request is 100m, cpu max limit to request ratio per Container is 4, but provided ratio is 10.000000] # 默认容器资源下限值cpu为500m,所以这里创建不成功# cpu修改成600m,可以创建成功 [root@master 16]# vim pod-request.yaml [root@master 16]# kubectl apply -f pod-request.yaml pod/pod-request created [root@master 16]# kubectl describe pod pod-request -n limit
0
0
0
浏览量2010
锅从天上来

K8S(一)—安装部署

安装部署前提以下的操作指导(在master)之前都是三台机器都需要执行关闭防火墙[root@k8smaster ~]# vim /etc/selinux/config [root@k8smaster ~]# swapoff -a [root@k8smaster ~]# vim /etc/fstab [root@k8smaster ~]# service firewalld stop Redirecting to /bin/systemctl stop firewalld.service [root@k8smaster ~]# systemctl disable firewalld Removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.service. Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service. 修改/etc/hosts文件[root@k8smaster1 ~]# cat /etc/hosts 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 192.168.2.210 k8smaster 192.168.2.211 k8snode1 192.168.2.212 k8snode2 建立免密通道(方便后续转文件)每台机器都要实现相互之间的通道(以master为例)生成密钥ssh-keygen把本地生成的密钥文件和私钥文件拷贝到远程主机ssh-copy-id k8smaster ssh-copy-id k8snode1 ssh-copy-id k8snode2测试通道是否建立成功ssh k8smaster ssh k8snode1 ssh k8snode2关闭交换分区swap,提升性能临时关闭swapoff -a永久关闭[root@k8smaster1 ~]# cat /etc/fstab # # /etc/fstab # Created by anaconda on Sat Jul 29 17:46:15 2023 # # Accessible filesystems, by reference, are maintained under '/dev/disk' # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info # /dev/mapper/centos-root / xfs defaults 0 0 UUID=104d6b80-24cf-4094-8d9a-09a9878f9895 /boot xfs defaults 0 0 /dev/mapper/centos-home /home xfs defaults 0 0 #/dev/mapper/centos-swap swap swap defaults 0 0 注释/dev/mapper/centos-swap swap swap defaults 0 0即可为什么要关闭swap交换分区?Swap是交换分区,如果机器内存不够,会使用swap分区,但是swap分区的性能较低,k8s设计的时候为了能提升性能,默认是不允许使用交换分区的。Kubeadm初始化的时候会检测swap是否关闭,如果没关闭,那就初始化失败。如果不想要关闭交换分区,安装k8s的时候可以指定–ignore-preflight-errors=Swap来解决。加载相关内核文件modprobe br_netfilterecho "modprobe br_netfilter" >> /etc/profilecat > /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 EOF​ 这是一个Linux命令,它的作用是将文本输入到/etc/sysctl.d/k8s.conf文件中。">“符号表示覆盖文件内容,如果文件不存在则会创建一个新文件。”<<EOF"表示输入的文本以EOF为结束标志​ 该命令在Kubernetes集群中通常用于配置内核参数,以优化集群的性能和稳定性。在这个例子中,EOF后面的文本应该包含一些内核参数的配置信息加载配置sysctl -p /etc/sysctl.d/k8s.conf[root@k8smaster1 ~]# sysctl -p /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1配置阿里云源yum install -y yum-utilsyum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo[root@k8smaster1 ~]# yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 已加载插件:fastestmirror adding repo from: http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo grabbing file http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo to /etc/yum.repos.d/docker-ce.repo repo saved to /etc/yum.repos.d/docker-ce.repo安装其他软件yum install -y yum-utils device-mapper-persistent-data lvm2 wget net-tools nfs-utils lrzsz gcc gcc-c++ make cmake libxml2-devel openssl-devel curl curl-devel unzip sudo ntp libaio-devel wget vim ncurses-devel autoconf automake zlib-devel python-devel epel-release openssh-server socat ipvsadm conntrack ntpdate telnet ipvsadm配置安装k8s组件需要的阿里云的repo源vim /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/ enabled=1 gpgcheck=0配置时间同步安装ntpdate命令yum install ntpdate -y跟网络时间做同步ntpdate cn.pool.ntp.org把时间同步做成计划任务crontab -e * */1 * * * /usr/sbin/ntpdate cn.pool.ntp.org重启crond服务service crond restart安装docker服务安装dockeryum install docker-ce-20.10.6 -y设置开启启动systemctl daemon-reload && systemctl restart docker编辑文件vim /etc/docker/daemon.json{ "registry-mirrors":["https://rsbud4vc.mirror.aliyuncs.com","https://registry.docker-cn.com","https://docker.mirrors.ustc.edu.cn","https://dockerhub.azk8s.cn","http://hub-mirror.c.163.com"], "exec-opts": ["native.cgroupdriver=systemd"] } systemctl daemon-reload && systemctl restart docker修改docker文件驱动为systemd,默认为cgroupfs,kubelet默认使用systemd,两者必须一致才可以。安装初始化k8s需要的软件包*(有1.23.6版本)yum install -y kubelet-1.20.6 kubeadm-1.20.6 kubectl-1.20.6设置开机启动systemctl enable kubeletKubeadm kubeadm是一个工具,用来初始化k8s集群的kubelet 安装在集群所有节点上,用于启动Pod的kubectl通过kubectl可以部署和管理应用,查看各种资源,创建、删除和更新各种组件把初始化k8s集群需要的离线镜像包上传到机器上,手动解压:docker load -i k8simage-1-20-6.tar.gz下面的操作仅在k8smaster执行使用kubeadm初始化k8s集群 kubeadm config print init-defaults > kubeadm.yaml[root@k8smaster1 ~]# ls anaconda-ks.cfg k8simage-1-20-6.tar.gz kubeadm.yaml改配置文件根据我们自己的需求修改配置,比如修改 imageRepository 的值,kube-proxy 的模式为 ipvs,初始化节点的时候需要指定cgroupDriver为systemd[root@k8smaster1 ~]# cat kubeadm.yaml apiVersion: kubeadm.k8s.io/v1beta2 bootstrapTokens: - groups: - system:bootstrappers:kubeadm:default-node-token token: abcdef.0123456789abcdef ttl: 24h0m0s usages: - signing - authentication kind: InitConfiguration localAPIEndpoint: advertiseAddress: 192.168.2.210 bindPort: 6443 nodeRegistration: criSocket: /var/run/dockershim.sock name: k8smaster1 taints: - effect: NoSchedule key: node-role.kubernetes.io/master --- apiServer: timeoutForControlPlane: 4m0s apiVersion: kubeadm.k8s.io/v1beta2 certificatesDir: /etc/kubernetes/pki clusterName: kubernetes controllerManager: {} dns: type: CoreDNS etcd: local: dataDir: /var/lib/etcd imageRepository: registry.aliyuncs.com/google_containers kind: ClusterConfiguration kubernetesVersion: v1.20.0 networking: dnsDomain: cluster.local serviceSubnet: 10.96.0.0/12 podSubnet: 10.244.0.0/16 scheduler: {} --- apiVersion: kubeproxy.config.k8s.io/v1alpha1 kind: KubeProxyConfiguration mode: ipvs --- apiVersion: kubelet.config.k8s.io/v1beta1 kind: KubeletConfiguration cgroupDriver: systemd ​ --image-repository registry.aliyuncs.com/google_containers为保证拉取镜像不到国外站点拉取,手动指定仓库地址为registry.aliyuncs.com/google_containers。kubeadm默认从k8s.gcr.io拉取镜像。​ mode: ipvs 表示kube-proxy代理模式是ipvs,如果不指定ipvs,会默认使用iptables,但是iptables效率低,所以我们生产环境建议开启ipvs,阿里云和华为云托管的K8s,也提供ipvs模式我们本地有导入到的离线镜像k8simage-1-20-6.tar.gz,所以会优先使用本地的镜像。基于kubeadm.yaml文件初始化k8skubeadm init --config=kubeadm.yaml --ignore-preflight-errors=SystemVerification显示如下,说明安装完成:mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config在k8smaster上查看加入节点的命令:kubeadm token create --print-join-command在k8snode1、k8snode2输入下面命令:kubeadm join 192.168.2.210:6443 --token ooveyk.k9pttn2esdowdej0 --discovery-token-ca-cert-hash sha256:69470ed1d44af1f049b11cb85ac4638829063a9df8002dc47de3260d6d34dfe7 在k8smaster查看集群节点状况[root@k8smaster1 ~]# kubectl get node NAME STATUS ROLES AGE VERSION k8smaster NotReady control-plane,master 11m v1.20.6 k8snode1 NotReady <none> 25s v1.20.6 k8snode2 NotReady <none> 18s v1.20.6 您在 /var/spool/mail/root 中有新邮件可以看到k8snode1、k8snode2的ROLES角色为空(),就表示这个节点是工作节点。​ 可以把k8snode1、k8snode2的ROLES变成work,按照如下方法: kubectl label node k8snode1 node-role.kubernetes.io/worker=worker kubectl label node k8snode2 node-role.kubernetes.io/worker=worker在k8smaster查看集群节点状况[root@k8smaster1 ~]# kubectl get node NAME STATUS ROLES AGE VERSION k8smaster NotReady control-plane,master 17m v1.20.6 k8snode1 NotReady worker 6m19s v1.20.6 k8snode2 NotReady worker 6m12s v1.20.6上面状态都是NotReady状态,说明没有安装网络插件k8smaster安装kubernetes网络组件-Calico下载配置文件地址:https://docs.tigera.io/calico/latest/manifests/calico.yamlkubectl apply -f calico.yam再次查看集群状态。[root@k8smaster1 ~]# kubectl get node NAME STATUS ROLES AGE VERSION k8smaster Ready control-plane,master 20m v1.20.6 k8snode1 Ready worker 9m20s v1.20.6 k8snode2 Ready worker 9m13s v1.20.6STATUS状态是Ready,说明k8s集群正常运行了[root@k8smaster ~]# kubectl get pod -n kube-system NAME READY STATUS RESTARTS AGE calico-kube-controllers-6949477b58-nwmr2 1/1 Running 0 70s calico-node-5jq26 1/1 Running 0 70s calico-node-lk4zv 1/1 Running 0 70s calico-node-n4742 1/1 Running 0 70s coredns-7f89b7bc75-7zdk5 1/1 Running 0 160m coredns-7f89b7bc75-x8jcr 1/1 Running 0 160m etcd-k8smaster 1/1 Running 0 160m kube-apiserver-k8smaster 1/1 Running 0 160m kube-controller-manager-k8smaster 1/1 Running 1 160m kube-proxy-pkt7c 1/1 Running 0 159m kube-proxy-pps8s 1/1 Running 0 2m15s kube-proxy-qgs8x 1/1 Running 0 160m kube-scheduler-k8smaster 这是一个使用 kubectl 工具在 Kubernetes 集群的 kube-system 命名空间中获取 Pod 信息的命令解析:kubectl: Kubernetes 命令行工具,用于与 Kubernetes 集群进行交互。get: kubectl 的子命令之一,用于从 Kubernetes 集群中获取资源的信息。pod: 要获取的资源类型,表示 Pod 对象。-n kube-system: 选项,指定要获取资源的命名空间为 kube-system。Kubernetes 中的命名空间是用于在集群中对资源进行逻辑隔离的一种机制。执行该命令将显示 kube-system 命名空间中所有 Pod 的名称及其相关信息,如状态、IP 地址、运行时间等。
0
0
0
浏览量2022
锅从天上来

K8S(七)—污点、容忍

污点、容忍官网地址:https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/taint-and-toleration/Kubernetes(通常简称为K8s)是一个用于容器编排和管理的开源平台。在Kubernetes中,污点(Taints)和容忍(Tolerations)是用于控制Pod调度的重要概念,它们允许您指定哪些节点可以接受哪些Pod。以下是有关污点和容忍的详细解释:污点(Taints):1.什么是污点:污点是一种节点级别的属性,它告诉Kubernetes哪些节点不适合运行特定类型的Pod。节点上的污点可以阻止Pod被调度到不适合的节点上。2.如何定义污点:污点由节点的管理员定义,它们是键值对的形式,包括:key:污点的名称,通常是一个字符串。value:污点的值,通常为空字符串。effect:污点的效果,可以是NoSchedule、PreferNoSchedule或NoExecute。NoSchedule:Pod将不会被调度到带有该污点的节点上。PreferNoSchedule:Kubernetes会尽量避免将Pod调度到带有该污点的节点上,但如果没有其他可用节点,仍然可以调度。NoExecute:对于已经运行在该节点上的Pod,如果它们不符合污点的要求,将被驱逐。设置污点[root@k8smaster taint_toleration]# kubectl describe node k8snode1|grep -i NoExecute Taints: cf=tencent:NoExecute取消污点[root@k8smaster taint_toleration]# kubectl taint node k8snode1 cf=tencent:NoExecute- node/k8snode1 untainted[root@k8smaster taint_toleration]# kubectl describe node k8snode1|grep -i NoExecute [root@k8smaster taint_toleration]# 容忍(Tolerations):1.什么是容忍:容忍是Pod级别的属性,它告诉Kubernetes该Pod可以容忍哪些节点上的污点。容忍允许Pod被调度到具有特定污点的节点上。2.如何定义容忍:容忍是在Pod的规范(Spec)中定义的,包括:key:与污点的key匹配。value:与污点的value匹配。operator:匹配操作符,可以是Equal(等于)、Exists(存在)等。effect:与污点的effect匹配。3.示例:假设您有一个Pod,它希望容忍名为gpu的污点,您可以使用以下方式定义容忍:tolerations: - key: gpu operator: Equal value: nvidia effect: NoSchedule如何一起使用污点和容忍:通过在节点上定义污点,您可以将一组节点标记为特定类型(例如GPU节点),然后通过在Pod规范中定义容忍,您可以确保只有需要GPU的Pod才会被调度到这些节点上。污点和容忍的结合可以为您提供更高的灵活性,以满足特定的部署需求。您可以根据需要在节点和Pod级别上定义多个污点和容忍。总之,污点和容忍是Kubernetes中用于控制Pod调度的强大机制,它们使得您可以更精确地管理Pod在集群中的位置,以满足特定的硬件或软件要求。这对于在多样化的硬件和环境条件下运行容器化应用程序非常有用。操作符(Equal、Exists)你可以在 Pod 规约中为 Pod 设置容忍度。 下面两个容忍度均与上面例子中使用 kubectl taint 命令创建的污点相匹配, 因此如果一个 Pod 拥有其中的任何一个容忍度,都能够被调度到 node1:tolerations: - key: "key1" operator: "Equal" value: "value1" effect: "NoSchedule" tolerations: - key: "key1" operator: "Exists" effect: "NoSchedule"这里是一个使用了容忍度的 Pod:pods/pod-with-toleration.yamlapiVersion: v1 kind: Pod metadata: name: nginx labels: env: test spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent tolerations: - key: "example-key" operator: "Exists" effect: "NoSchedule"operator 的默认值是 Equal。一个容忍度和一个污点相“匹配”是指它们有一样的键名和效果,并且:如果 operator 是 Exists(此时容忍度不能指定 value),或者如果 operator 是 Equal,则它们的 value 应该相等。说明:存在两种特殊情况:如果一个容忍度的 key 为空且 operator 为 Exists, 表示这个容忍度与任意的 key、value 和 effect 都匹配,即这个容忍度能容忍任何污点。如果 effect 为空,则可以与所有键名 key1 的效果相匹配。下面的例子表示任何污点都可以接受tolerations: - key:"" operator: "Exists" value:"" effect:"" 上述例子中 effect 使用的值为 NoSchedule,你也可以使用另外一个值 PreferNoSchedule。 这是“优化”或“软”版本的 NoSchedule —— 系统会 尽量 避免将 Pod 调度到存在其不能容忍污点的节点上, 但这不是强制的。effect 的值还可以设置为 NoExecute,下文会详细描述这个值。你可以给一个节点添加多个污点,也可以给一个 Pod 添加多个容忍度设置。 Kubernetes 处理多个污点和容忍度的过程就像一个过滤器:从一个节点的所有污点开始遍历, 过滤掉那些 Pod 中存在与之相匹配的容忍度的污点。余下未被过滤的污点的 effect 值决定了 Pod 是否会被分配到该节点。需要注意以下情况:如果未被忽略的污点中存在至少一个 effect 值为 NoSchedule 的污点, 则 Kubernetes 不会将 Pod 调度到该节点。如果未被忽略的污点中不存在 effect 值为 NoSchedule 的污点, 但是存在至少一个 effect 值为 PreferNoSchedule 的污点, 则 Kubernetes 会 尝试 不将 Pod 调度到该节点。如果未被忽略的污点中存在至少一个 effect 值为 NoExecute 的污点, 则 Kubernetes 不会将 Pod 调度到该节点(如果 Pod 还未在节点上运行), 并且会将 Pod 从该节点驱逐(如果 Pod 已经在节点上运行)。例如,假设你给一个节点添加了如下污点:kubectl taint nodes node1 key1=value1:NoSchedule kubectl taint nodes node1 key1=value1:NoExecute kubectl taint nodes node1 key2=value2:NoSchedule假定某个 Pod 有两个容忍度:tolerations: - key: "key1" operator: "Equal" value: "value1" effect: "NoSchedule" - key: "key1" operator: "Equal" value: "value1" effect: "NoExecute"在这种情况下,上述 Pod 不会被调度到上述节点,因为其没有容忍度和第三个污点相匹配。 但是如果在给节点添加上述污点之前,该 Pod 已经在上述节点运行, 那么它还可以继续运行在该节点上,因为第三个污点是三个污点中唯一不能被这个 Pod 容忍的。通常情况下,如果给一个节点添加了一个 effect 值为 NoExecute 的污点, 则任何不能忍受这个污点的 Pod 都会马上被驱逐,任何可以忍受这个污点的 Pod 都不会被驱逐。 但是,如果 Pod 存在一个 effect 值为 NoExecute 的容忍度指定了可选属性 tolerationSeconds 的值,则表示在给节点添加了上述污点之后, Pod 还能继续在节点上运行的时间。例如,tolerations: - key: "key1" operator: "Equal" value: "value1" effect: "NoExecute" tolerationSeconds: 3600这表示如果这个 Pod 正在运行,同时一个匹配的污点被添加到其所在的节点, 那么 Pod 还将继续在节点上运行 3600 秒,然后被驱逐。 如果在此之前上述污点被删除了,则 Pod 不会被驱逐。例子使用yaml启动pod[root@k8smaster taint_toleration]# cat pod.yaml apiVersion: v1 kind: Pod metadata: name: demo-pod namespace: default labels: app: myapp env: dev spec: nodeName: k8snode1 containers: - name: busybox image: busybox:latest imagePullPolicy: IfNotPresent command: - "/bin/sh" - "-c" - "sleep 3600"此时,k8snode1和k8snode2都没有污点,都可以正常被调度,但是在yaml文件在指定了要运行在那个节点上。[root@k8smaster taint_toleration]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES demo-pod 1/1 Running 0 20s 10.244.249.24 k8snode1 <none> <none> nginx-deployment-559d658b74-75fpp 1/1 Running 0 100m 10.244.249.21 k8snode1 <none> <none> nginx-deployment-559d658b74-j6rdd 1/1 Running 0 101m 10.244.249.20 k8snode1 <none> <none> nginx-deployment-559d658b74-kh8jb 1/1 Running 0 101m 10.244.185.250 k8snode2 <none> <none> 设置污点[root@k8smaster taint_toleration]# kubectl describe node k8smaster|grep -i taint Taints: node-role.kubernetes.io/master:NoSchedule[root@k8smaster taint_toleration]# kubectl taint nodes k8snode1 cf=tencent:NoExecute node/k8snode1 tainted [root@k8smaster taint_toleration]# kubectl describe node k8snode1|grep -i taint Taints: cf=tencent:NoExecutedemo-pod 会停止运行[root@k8smaster taint_toleration]# cat pod.yaml apiVersion: v1 kind: Pod metadata: name: demo-pod namespace: default labels: app: myapp env: dev spec: nodeName: k8snode1 containers: - name: busybox image: busybox:latest imagePullPolicy: IfNotPresent command: - "/bin/sh" - "-c" - "sleep 3600" tolerations: - key: "cf" operator: "Equal" value: "tencent" effect: "NoExecute" 将ymal文件进行修改,将容忍度也设置为k8snode1可以接受的程度,如下: tolerations: - key: "cf" operator: "Equal" value: "tencent" effect: "NoExecute"可以看到demo-pod 重新运行了[root@k8smaster taint_toleration]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES demo-pod 1/1 Running 0 13h 10.244.249.25 k8snode1 <none> <none>基于污点的驱逐特性状态: Kubernetes v1.18 [stable]前文提到过污点的效果值 NoExecute 会影响已经在节点上运行的如下 Pod:如果 Pod 不能忍受这类污点,Pod 会马上被驱逐。如果 Pod 能够忍受这类污点,但是在容忍度定义中没有指定 tolerationSeconds, 则 Pod 还会一直在这个节点上运行。如果 Pod 能够忍受这类污点,而且指定了 tolerationSeconds, 则 Pod 还能在这个节点上继续运行这个指定的时间长度。当某种条件为真时,节点控制器会自动给节点添加一个污点。当前内置的污点包括:node.kubernetes.io/not-ready:节点未准备好。这相当于节点状况 Ready 的值为 “False”。node.kubernetes.io/unreachable:节点控制器访问不到节点. 这相当于节点状况 Ready 的值为 “Unknown”。node.kubernetes.io/memory-pressure:节点存在内存压力。node.kubernetes.io/disk-pressure:节点存在磁盘压力。node.kubernetes.io/pid-pressure: 节点的 PID 压力。node.kubernetes.io/network-unavailable:节点网络不可用。node.kubernetes.io/unschedulable: 节点不可调度。node.cloudprovider.kubernetes.io/uninitialized:如果 kubelet 启动时指定了一个“外部”云平台驱动, 它将给当前节点添加一个污点将其标志为不可用。在 cloud-controller-manager 的一个控制器初始化这个节点后,kubelet 将删除这个污点。在节点被排空时,节点控制器或者 kubelet 会添加带有 NoExecute 效果的相关污点。 如果异常状态恢复正常,kubelet 或节点控制器能够移除相关的污点。在某些情况下,当节点不可达时,API 服务器无法与节点上的 kubelet 进行通信。 在与 API 服务器的通信被重新建立之前,删除 Pod 的决定无法传递到 kubelet。 同时,被调度进行删除的那些 Pod 可能会继续运行在分区后的节点上。说明:控制面会限制向节点添加新污点的速率。这一速率限制可以管理多个节点同时不可达时 (例如出现网络中断的情况),可能触发的驱逐的数量。你可以为 Pod 设置 tolerationSeconds,以指定当节点失效或者不响应时, Pod 维系与该节点间绑定关系的时长。比如,你可能希望在出现网络分裂事件时,对于一个与节点本地状态有着深度绑定的应用而言, 仍然停留在当前节点上运行一段较长的时间,以等待网络恢复以避免被驱逐。 你为这种 Pod 所设置的容忍度看起来可能是这样:tolerations: - key: "node.kubernetes.io/unreachable" operator: "Exists" effect: "NoExecute" tolerationSeconds: 6000说明:Kubernetes 会自动给 Pod 添加针对 node.kubernetes.io/not-ready 和 node.kubernetes.io/unreachable 的容忍度,且配置 tolerationSeconds=300, 除非用户自身或者某控制器显式设置此容忍度。这些自动添加的容忍度意味着 Pod 可以在检测到对应的问题之一时,在 5 分钟内保持绑定在该节点上。DaemonSet 中的 Pod 被创建时, 针对以下污点自动添加的 NoExecute 的容忍度将不会指定 tolerationSeconds:node.kubernetes.io/unreachablenode.kubernetes.io/not-ready这保证了出现上述问题时 DaemonSet 中的 Pod 永远不会被驱逐。基于节点状态添加污点控制平面使用节点控制器自动创建 与节点状况 对应的、效果为 NoSchedule 的污点。调度器在进行调度时检查污点,而不是检查节点状况。这确保节点状况不会直接影响调度。 例如,如果 DiskPressure 节点状况处于活跃状态,则控制平面添加 node.kubernetes.io/disk-pressure 污点并且不会调度新的 Pod 到受影响的节点。 如果 MemoryPressure 节点状况处于活跃状态,则控制平面添加 node.kubernetes.io/memory-pressure 污点。对于新创建的 Pod,可以通过添加相应的 Pod 容忍度来忽略节点状况。 控制平面还在具有除 BestEffort 之外的 QoS 类的 Pod 上添加 node.kubernetes.io/memory-pressure 容忍度。 这是因为 Kubernetes 将 Guaranteed 或 Burstable QoS 类中的 Pod(甚至没有设置内存请求的 Pod) 视为能够应对内存压力,而新创建的 BestEffort Pod 不会被调度到受影响的节点上。DaemonSet 控制器自动为所有守护进程添加如下 NoSchedule 容忍度,以防 DaemonSet 崩溃:node.kubernetes.io/memory-pressurenode.kubernetes.io/disk-pressurenode.kubernetes.io/pid-pressure (1.14 或更高版本)node.kubernetes.io/unschedulable (1.10 或更高版本)node.kubernetes.io/network-unavailable (只适合主机网络配置)添加上述容忍度确保了向后兼容,你也可以选择自由向 DaemonSet 添加容忍度。
0
0
0
浏览量2012
锅从天上来

K8s(九)—volume.md

volumehttps://kubernetes.io/zh-cn/docs/concepts/storage/volumes/在Kubernetes中,Volume是一种抽象的概念,用于将持久化存储附加到Pod中,以便容器可以读取和写入数据。Volumes提供了一种在Pod之间共享数据、将数据持久化存储以及将数据从主机挂载到容器中的方法。以下是关于Kubernetes中Volume的详细解释:1.Volume的基本概念:•容器存储抽象: Volume是Kubernetes的容器存储抽象,它使容器能够在不同的Pod之间共享数据,或者将数据持久化存储到底层存储设备上。•生命周期绑定: Volume的生命周期与Pod紧密绑定,当Pod被删除时,与之关联的Volume也会被删除(除非它被配置为保留)。•挂载点: Volume在Pod中通过一个或多个挂载点(mount points)进行访问。容器可以将这些挂载点用作文件或目录的存储位置。2.内置Volume类型:Kubernetes支持多种内置Volume类型,每种类型都有不同的用途和特性,包括但不限于:•EmptyDir: 空目录,生命周期与Pod相同,适合临时存储。•HostPath: 主机文件系统的目录,适合与主机共享文件。•PersistentVolumeClaim (PVC): PVC允许动态分配持久卷,并且可以用于数据持久性存储。•ConfigMap和Secret: 将ConfigMap和Secret数据作为文件或环境变量挂载到容器中。3.持久卷(Persistent Volumes)和持久卷声明(Persistent Volume Claims):•持久卷(PV)是集群级别的存储资源,它们独立于Pod的生命周期。•持久卷声明(PVC)是Pod对PV的请求。PVC允许开发人员声明他们需要多少存储以及存储的属性(例如访问模式和存储类)。•PVC与PV进行绑定,Pod再引用PVC,使得数据持久化存储可以动态地分配给Pod。4.存储类(Storage Class):•存储类是一种用于动态分配PV的资源管理策略。它允许管理员定义不同类型的存储(如本地存储、网络存储等)以及各种参数。•当PVC没有指定存储卷时,存储类可以根据要求动态创建PV。5.Volume的使用场景:•共享配置文件: 使用ConfigMap Volume或Secret Volume将配置文件共享给多个容器。•数据持久化: 使用PersistentVolume和PersistentVolumeClaim来实现数据的持久性存储,例如数据库数据。•临时存储: 使用EmptyDir Volume来创建在Pod之间共享的临时目录。•日志和监控数据: 使用HostPath Volume将日志文件或监控数据存储到宿主主机上以供分析。6.Volume的声明:•在Pod的定义中,可以通过volumes字段声明要使用的Volume。•在容器的定义中,可以通过volumeMounts字段将Volume挂载到容器的指定路径。7.示例:以下是一个使用PersistentVolumeClaim和Volume的示例:apiVersion: v1 kind: PersistentVolumeClaim metadata: name: my-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi --- apiVersion: v1 kind: Pod metadata: name: my-pod spec: volumes: - name: my-storage persistentVolumeClaim: claimName: my-pvc containers: - name: my-container image: my-image volumeMounts: - mountPath: /data name: my-storage 在此示例中,我们创建了一个PersistentVolumeClaim(my-pvc),然后在Pod中使用该PVC来创建一个Volume,并将它挂载到容器的/data路径上。总之,Kubernetes的Volume是一种强大的机制,用于处理容器存储需求,它提供了多种选项,使得在容器化应用程序中管理数据变得更加灵活和可靠。不同类型的Volume适用于不同的用例,根据应用程序的需求来选择适当的Volume类型是非常重要的。configMap介绍​ 在Kubernetes中,ConfigMap(配置映射)是一种用于将配置数据以键值对的形式存储并注入到容器中的资源。ConfigMap允许将配置信息从容器镜像中分离出来,从而使配置更易于管理和修改。以下是关于Kubernetes中ConfigMap的详细解释:1.ConfigMap的基本概念: **配置数据存储**: ConfigMap用于存储配置数据,这些数据通常以**键值对**的形式存在。键值对中的键(key)是配置的名称,而值(value)是配置的内容。 **解耦配置**: ConfigMap将配置数据从应用程序容器中分离出来,从而使得应用程序可以更容易地配置和修改,而不需要重新构建镜像。 **不敏感数据**: ConfigMap通常用于存储非敏感数据,如应用程序配置、环境变量、命令行参数等。2.创建和管理ConfigMap: **命令行创建**:可以使用`kubectl create configmap`命令或从YAML文件创建ConfigMap。例如: ``` kubectl create configmap my-config --from-literal=KEY1=VALUE1 --from-literal=KEY2=VALUE2 ``` **YAML定义**:以下是一个ConfigMap的YAML示例: ``` apiVersion: v1 kind: ConfigMap metadata: name: my-config data: KEY1: VALUE1 KEY2: VALUE2 ``` **从文件创建**:还可以从文件创建ConfigMap,例如从配置文件中读取键值对列表。将ConfigMap注入到Pod中: ConfigMap可以通过以下方式注入到Pod中: - **作为环境变量**: 使用`env`字段将ConfigMap的数据注入为容器的环境变量。 - **作为卷(Volume)**: 将ConfigMap数据作为文件挂载到容器中的某个路径上,容器可以读取这些文件作为配置文件。 示例:以下是一个将ConfigMap作为环境变量注入到Pod中的示例: ``` apiVersion: v1 kind: Pod metadata: name: my-pod spec: containers: - name: my-container image: my-image env: - name: KEY1 valueFrom: configMapKeyRef: name: my-config key: KEY1 ``` 3.使用场景: **应用程序配置**: 将应用程序的配置信息(如数据库连接字符串、端口号、日志级别等)存储在ConfigMap中,使应用程序更易于配置和管理。 **环境变量注入**: 使用ConfigMap将环境变量注入到容器中,以自定义容器的行为。 **配置文件挂载**: 将配置文件存储在ConfigMap中,并将其作为卷挂载到容器中,以供应用程序读取。4.更新和维护: ConfigMap的数据可以随时更新,Kubernetes会自动将更新后的数据应用到Pod中。 当ConfigMap更新时,使用该ConfigMap的Pod可以实时感知到这些变化。​ 总之,ConfigMap是Kubernetes中一种重要的资源,用于存储和注入配置数据,以实现应用程序的可配置性和可维护性。通过将配置数据与容器镜像分离,ConfigMap使得应用程序的配置更加灵活,允许在不重新构建容器镜像的情况下进行配置更改。这在微服务和容器化应用程序中非常有用,因为它使配置管理变得更加简单且易于维护。官网​ configMap卷提供了向 Pod 注入配置数据的方法。 ConfigMap 对象中存储的数据可以被 configMap 类型的卷引用,然后被 Pod 中运行的容器化应用使用。引用 configMap 对象时,你可以在卷中通过它的名称来引用。 你可以自定义 ConfigMap 中特定条目所要使用的路径。 下面的配置显示了如何将名为 log-config 的 ConfigMap 挂载到名为 configmap-pod 的 Pod 中:apiVersion: v1 kind: Pod metadata: name: configmap-pod spec: containers: - name: test image: busybox:1.28 volumeMounts: - name: config-vol mountPath: /etc/config volumes: - name: config-vol configMap: name: log-config items: - key: log_level path: log_level log-config ConfigMap 以卷的形式挂载,并且存储在 log_level 条目中的所有内容都被挂载到 Pod 的 /etc/config/log_level 路径下。 请注意,这个路径来源于卷的 mountPath 和 log_level 键对应的 path。说明:在使用 ConfigMap 之前你首先要创建它。ConfigMap 总是以 readOnly 的模式挂载。容器以 subPath 卷挂载方式使用 ConfigMap 时,将无法接收 ConfigMap 的更新。文本数据挂载成文件时采用 UTF-8 字符编码。如果使用其他字符编码形式,可使用 binaryData 字段。例子https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/configure-pod-configmap/# 将示例文件下载到 `/root/configmap/` 目录 wget https://kubernetes.io/examples/configmap/game.properties wget https://kubernetes.io/examples/configmap/ui.properties # 创建 ConfigMap kubectl create configmap game-config --from-file=/root/configmap/ [root@k8smaster configmap]# kubectl get cm NAME DATA AGE game-config 2 39s kube-root-ca.crt 1 2d23h [root@k8smaster configmap]# kubectl create configmap game-config --from-file=/root/configmap/ configmap/game-config created [root@k8smaster configmap]# kubectl get gf error: the server doesn't have a resource type "gf" [root@k8smaster configmap]# kubectl get cm NAME DATA AGE game-config 2 39s kube-root-ca.crt 1 2d23h [root@k8smaster configmap]# kubectl describe configmaps game-config Name: game-config Namespace: default Labels: <none> Annotations: <none> Data ==== game.properties: ---- enemies=aliens lives=3 enemies.cheat=true enemies.cheat.level=noGoodRotten secret.code.passphrase=UUDDLRLRBABAS secret.code.allowed=true secret.code.lives=30 ui.properties: ---- color.good=purple color.bad=yellow allow.textmode=true how.nice.to.look=fairlyNice Events: <none> [root@k8smaster configmap]# kubectl get configmaps game-config -o yaml >/root/configmap/game.yaml [root@k8smaster configmap]# ls game.properties game.yaml ui.properties基于文件生成 ConfigMapcat <<EOF >./kustomization.yaml configMapGenerator: - name: game-config-4 files: - configmap/game.properties EOF应用(Apply)kustomization 目录创建 ConfigMap 对象: kubectl apply -k . [root@k8smaster ~]# kubectl get cm NAME DATA AGE game-config 2 8m9s game-config-4-m9dm2f92bt 1 59s kube-root-ca.crt 1 2d23h [root@k8smaster ~]# kubectl describe configmaps/game-config-4-m9dm2f92bt Name: game-config-4-m9dm2f92bt Namespace: default Labels: <none> Annotations: <none> Data ==== game.properties: ---- enemies=aliens lives=3 enemies.cheat=true enemies.cheat.level=noGoodRotten secret.code.passphrase=UUDDLRLRBABAS secret.code.allowed=true secret.code.lives=30 Events: <none>使用 ConfigMap 数据定义容器环境变量使用单个 ConfigMap 中的数据定义容器环境变量•在 ConfigMap 中将环境变量定义为键值对:kubectl create configmap special-config --from-literal=special.how=very这是一个 kubectl 命令,用于在Kubernetes集群中创建一个名为 special-config 的ConfigMap,并将一个键值对添加到该ConfigMap中。具体来说,这个命令的含义如下:•kubectl create configmap special-config:这部分命令告诉Kubernetes创建一个名为 special-config 的ConfigMap。•--from-literal=special.how=very:这部分是 kubectl 命令的选项,用于指定要添加到ConfigMap中的数据。具体来说,它包含了一个键值对,键是 special.how,值是 very。这意味着创建的ConfigMap中将包含一个键为 special.how,值为 very 的项。运行这个命令后,将在Kubernetes集群中创建一个名为 special-config 的ConfigMap,该ConfigMap包含一个键为 special.how,值为 very 的配置项。这个ConfigMap可以被Pod引用,以便在容器中使用这个配置项的值作为环境变量、命令参数或其他配置选项。例如,可以在上一个回答中提到的Pod配置中引用这个ConfigMap,将 special.how 的值分配给 SPECIAL_LEVEL_KEY 环境变量。[root@k8smaster ~]# kubectl get cm NAME DATA AGE game-config 2 12m game-config-4-m9dm2f92bt 1 5m7s kube-root-ca.crt 1 2d23h special-config 1 16s[root@k8smaster ~]# kubectl describe configmaps/special-config Name: special-config Namespace: default Labels: <none> Annotations: <none> Data ==== special.how: ---- very Events: <none>•将 ConfigMap 中定义的 special.how 赋值给 Pod 规约中的 SPECIAL_LEVEL_KEY 环境变量。创建 pods/pod-single-configmap-env-variable.yaml[root@k8smaster configmap]# ls game.properties game.yaml pod-single-configmap-env-variable.yaml ui.properties [root@k8smaster configmap]# wget https://kubernetes.io/examples/pods/pod-single-configmap-env-variable.yaml --no-check-certificateapiVersion: v1 kind: Pod metadata: name: dapi-test-pod spec: containers: - name: test-container image: busybox imagePullPolicy: IfNotPresent command: [ "/bin/sh"] args: ["-c","env ;while true; do echo hello; sleep 100;done"] env: # Define the environment variable - name: SPECIAL_LEVEL_KEY valueFrom: configMapKeyRef: # The ConfigMap containing the value you want to assign to SPECIAL_LEVEL_KEY name: special-config # Specify the key associated with the value key: special.how restartPolicy: Never 这是一个Kubernetes Pod的配置文件,用于创建一个名为 “dapi-test-pod” 的Pod。以下是配置文件中各部分的详细解释:apiVersion 和 kind:•apiVersion: v1 表示使用Kubernetes的v1版本API。•kind: Pod 指定创建的资源类型为Pod。metadata:•name: dapi-test-pod 定义了Pod的名称为 “dapi-test-pod”。spec:•containers:这是一个容器列表,用于定义Pod中的容器。•name: test-container:定义了容器的名称为 “test-container”。•image: busybox:指定了容器要使用的镜像,这里是一个名为 “busybox” 的轻量级Linux发行版。•imagePullPolicy: IfNotPresent:这表示如果本地已经存在相同的镜像,就使用它,否则不拉取新的镜像。•command和args:这两个字段定义了容器的启动命令和参数。•command: [ "/bin/sh"]:指定容器要执行的命令为 “/bin/sh”。•args: ["-c","env ;while true; do echo hello; sleep 100;done"]:这些参数将传递给命令,容器将在启动后运行 /bin/sh -c "env ;while true; do echo hello; sleep 100;done" 这个Shell命令。•env:这里定义了容器的环境变量。•name: SPECIAL_LEVEL_KEY:指定环境变量的名称为 “SPECIAL_LEVEL_KEY”。•valueFrom:这里使用了 valueFrom 来从ConfigMap引用值。•configMapKeyRef:这是引用ConfigMap的方式。•name: special-config:指定了ConfigMap的名称为 “special-config”。•key: special.how:指定了要引用的ConfigMap中的键为 “special.how”。•restartPolicy: Never:定义了Pod的重启策略为 “Never”,这意味着一旦容器退出,Pod将不会自动重启。​ 这个配置文件创建了一个Pod,其中包含一个名为 “test-container” 的容器,该容器使用BusyBox镜像,运行一个无限循环的Shell命令,每隔100秒输出 “hello”。此容器还引用了一个名为 “special-config” 的ConfigMap,并将其中的 “special.how” 键的值分配给环境变量 “SPECIAL_LEVEL_KEY”。这个配置演示了如何在Pod中使用ConfigMap来配置容器的环境变量。[root@k8smaster configmap]# kubectl get pod NAME READY STATUS RESTARTS AGE dapi-test-pod 1/1 Running 0 21s test-pd 1/1 Running 0 55m[root@k8smaster configmap]# kubectl logs dapi-test-pod *** SPECIAL_LEVEL_KEY=very ***现在,Pod 的输出包含环境变量 SPECIAL_LEVEL_KEY=very。EmptyDirapiVersion: v1 kind: Pod metadata: name: test-pd spec: containers: - image: registry.k8s.io/test-webserver name: test-container volumeMounts: - mountPath: /cache name: cache-volume volumes: - name: cache-volume emptyDir: sizeLimit: 500Mi 启用pod[root@k8smaster volume]# kubectl apply -f nginx.yaml pod/test-pd created [root@k8smaster volume]# kubectl get pod NAME READY STATUS RESTARTS AGE test-pd 1/1 Running 0 6s进入容器里面,进入卷里面创建文件[root@k8smaster volume]# kubectl exec -it test-pd -- bash root@test-pd:/# ls bin cache docker-entrypoint.d etc lib media opt root sbin sys usr boot dev docker-entrypoint.sh home lib64 mnt proc run srv tmp var root@test-pd:/# cd cache/ root@test-pd:/cache# ls root@test-pd:/cache# mkdir test 查找pod调度到那个node上[root@k8smaster volume]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES test-pd 1/1 Running 0 85s 10.244.185.201 k8snode2 <none> <none>在k8snode2查找卷[root@k8snode2 ~]# find / -name "test" *** /var/lib/kubelet/pods/bfe54579-84e1-4ef2-b85e-722b84d848d1/volumes/kubernetes.io~empty-dir/cache-volume/test *** [root@k8snode2 ~]# cd /var/lib/kubelet/pods/bfe54579-84e1-4ef2-b85e-722b84d848d1/volumes/kubernetes.io~empty-dir/cache-volume/test [root@k8snode2 test]# ls [root@k8snode2 test]# cd .. [root@k8snode2 cache-volume]# ls testhostPath警告:HostPath 卷存在许多安全风险,最佳做法是尽可能避免使用 HostPath。 当必须使用 HostPath 卷时,它的范围应仅限于所需的文件或目录,并以只读方式挂载。如果通过 AdmissionPolicy 限制 HostPath 对特定目录的访问,则必须要求 volumeMounts 使用 readOnly 挂载以使策略生效。hostPath 卷能将主机节点文件系统上的文件或目录挂载到你的 Pod 中。 虽然这不是大多数 Pod 需要的,但是它为一些应用程序提供了强大的逃生舱。例如,hostPath 的一些用法有:•运行一个需要访问 Docker 内部机制的容器;可使用 hostPath 挂载 /var/lib/docker 路径。•在容器中运行 cAdvisor 时,以 hostPath 方式挂载 /sys。•允许 Pod 指定给定的 hostPath 在运行 Pod 之前是否应该存在,是否应该创建以及应该以什么方式存在。除了必需的 path 属性之外,你可以选择性地为 hostPath 卷指定 type。支持的 type 值如下:当使用这种类型的卷时要小心,因为:•HostPath 卷可能会暴露特权系统凭据(例如 Kubelet)或特权 API(例如容器运行时套接字),可用于容器逃逸或攻击集群的其他部分。•具有相同配置(例如基于同一 PodTemplate 创建)的多个 Pod 会由于节点上文件的不同而在不同节点上有不同的行为。•下层主机上创建的文件或目录只能由 root 用户写入。 你需要在特权容器中以 root 身份运行进程,或者修改主机上的文件权限以便容器能够写入 hostPath 卷。hostPath 配置示例apiVersion: v1 kind: Pod metadata: name: test-pd-2 spec: containers: - image: nginx imagePullPolicy: IfNotPresent name: ydhnginx-2 volumeMounts: - mountPath: /ydhdata name: cache-volume-2 volumes: - name: cache-volume-2 hostPath: # 宿主上目录位置 path: /data # 此字段为可选 type: DirectoryOrCreate 进入容器创建文件[root@k8smaster volume]# kubectl exec -it test-pd-2 -- bash root@test-pd-2:/# ls bin docker-entrypoint.d home media proc sbin tmp ydhdata boot docker-entrypoint.sh lib mnt root srv usr dev etc lib64 opt run sys var root@test-pd-2:/# cd ydhdata/ root@test-pd-2:/ydhdata# mkdir ydhtest [root@k8snode2 /]# cd data/ [root@k8snode2 data]# ls ydhtestnfsnfs 卷能将 NFS (网络文件系统) 挂载到你的 Pod 中。 不像 emptyDir 那样会在删除 Pod 的同时也会被删除,nfs 卷的内容在删除 Pod 时会被保存,卷只是被卸载。 这意味着 nfs 卷可以被预先填充数据,并且这些数据可以在 Pod 之间共享。apiVersion: v1 kind: Pod metadata: name: test-pd spec: containers: - image: registry.k8s.io/test-webserver name: test-container volumeMounts: - mountPath: /my-nfs-data name: test-volume volumes: - name: test-volume nfs: server: my-nfs-server.example.com path: /my-nfs-volume readOnly: true 说明:在使用 NFS 卷之前,你必须运行自己的 NFS 服务器并将目标 share 导出备用。还需要注意,不能在 Pod spec 中指定 NFS 挂载可选项。 可以选择设置服务端的挂载可选项,或者使用 /etc/nfsmount.conf。 此外,还可以通过允许设置挂载可选项的持久卷挂载 NFS 卷。如需了解用持久卷挂载 NFS 卷的示例,请参考 NFS 示例。persistentVolumeClaimpersistentVolumeClaim 卷用来将持久卷(PersistentVolume)挂载到 Pod 中。 持久卷申领(PersistentVolumeClaim)是用户在不知道特定云环境细节的情况下“申领”持久存储(例如 GCE PersistentDisk 或者 iSCSI 卷)的一种方法。
0
0
0
浏览量2009
锅从天上来

K8S(三)—组件

k8s组件控制平面组件(Control Plane Componentskube-apiserver​ API 服务器是 Kubernetes 控制平面的组件, 该组件负责公开了 Kubernetes API,负责处理接受请求的工作。 API 服务器是 Kubernetes 控制平面的前端。查看容器[root@k8smaster1 ~]# docker ps |grep api 0c251ffb3487 ca9843d3b545 "kube-apiserver --ad…" 2 hours ago Up 2 hours k8s_kube-apiserver_kube-apiserver-k8smaster_kube-system_8825a4339e5863527f01ed21491f2931_0 11f48841cfaa registry.aliyuncs.com/google_containers/pause:3.2 "/pause" 2 hours ago Up 2 hours k8s_POD_kube-apiserver-k8smaster_kube-system_8825a4339e5863527f01ed21491f2931_0查看端口[root@k8smaster1 ~]# netstat -anpult|grep "LISTEN.*apiserver " tcp6 0 0 :::6443 :::* LISTEN 5036/kube-apiserveretcd一致且高可用的键值存储,用作 Kubernetes 所有集群数据的后台数据库。[root@k8smaster1 ~]# docker ps |grep etcd 57e6d68cfb35 0369cf4303ff "etcd --advertise-cl…" 2 hours ago Up 2 hours k8s_etcd_etcd-k8smaster_kube-system_023c87e09bfa28e7117663bc22dbde5e_0 d660b8dc5481 registry.aliyuncs.com/google_containers/pause:3.2 "/pause" 2 hours ago Up 2 hours k8s_POD_etcd-k8smaster_kube-system_023c87e09bfa28e7117663bc22dbde5e_0 kube-schedulerkube-scheduler 是控制平面的组件, 负责监视新创建的、未指定运行节点(node)的 Pods, 并选择节点来让 Pod 在上面运行。​ 调度决策考虑的因素包括单个 Pod 及 Pods 集合的资源需求、软硬件及策略约束、 亲和性及反亲和性规范、数据位置、工作负载间的干扰及最后时限。[root@k8smaster1 ~]# docker ps|grep kube-scheduler c57c8eeadb77 3138b6e3d471 "kube-scheduler --au…" 2 hours ago Up 2 hours k8s_kube-scheduler_kube-scheduler-k8smaster_kube-system_0378cf280f805e38b5448a1eceeedfc4_0 b3c2057c6508 registry.aliyuncs.com/google_containers/pause:3.2 "/pause" 2 hours ago Up 2 hours k8s_POD_kube-scheduler-k8smaster_kube-system_0378cf280f805e38b5448a1eceeedfc4_0查看端口[root@k8smaster1 ~]# netstat -anpult|grep kube-scheduler tcp 0 0 127.0.0.1:10259 0.0.0.0:* LISTEN 4730/kube-scheduler tcp 0 0 192.168.2.210:54988 192.168.2.210:6443 ESTABLISHED 4730/kube-scheduler tcp 0 0 192.168.2.210:54992 192.168.2.210:6443 ESTABLISHED 4730/kube-scheduler kube-controller-manager​ kube-controller-manager 是控制平面的组件, 负责运行控制器进程。​ 从逻辑上讲, 每个控制器都是一个单独的进程, 但是为了降低复杂性,它们都被编译到同一个可执行文件,并在同一个进程中运行有许多不同类型的控制器。以下是一些例子:节点控制器(Node Controller):负责在节点出现故障时进行通知和响应任务控制器(Job Controller):监测代表一次性任务的 Job 对象,然后创建 Pods 来运行这些任务直至完成端点分片控制器(EndpointSlice controller):填充端点分片(EndpointSlice)对象(以提供 Service 和 Pod 之间的链接)。服务账号控制器(ServiceAccount controller):为新的命名空间创建默认的服务账号(ServiceAccount)。副本控制器部署控制器cloud-controller-manager​ 一个 Kubernetes 控制平面]组件, 嵌入了特定于云平台的控制逻辑。 云控制器管理器(Cloud Controller Manager)允许你将你的集群连接到云提供商的 API 之上, 并将与该云平台交互的组件同与你的集群交互的组件分离开来。​ cloud-controller-manager 仅运行特定于云平台的控制器。 因此如果你在自己的环境中运行 Kubernetes,或者在本地计算机中运行学习环境, 所部署的集群不需要有云控制器管理器。​ 与 kube-controller-manager 类似,cloud-controller-manager 将若干逻辑上独立的控制回路组合到同一个可执行文件中, 供你以同一进程的方式运行。 你可以对其执行水平扩容(运行不止一个副本)以提升性能或者增强容错能力。下面的控制器都包含对云平台驱动的依赖:节点控制器(Node Controller):用于在节点终止响应后检查云提供商以确定节点是否已被删除路由控制器(Route Controller):用于在底层云基础架构中设置路由服务控制器(Service Controller):用于创建、更新和删除云提供商负载均衡器Node 组件节点组件会在每个节点上运行,负责维护运行的 Pod 并提供 Kubernetes 运行环境。kubelet(单独的进程)kubelet 会在集群中每个节点(node)上运行。 它保证容器(containers)都运行在 Pod中。​ kubelet 接收一组通过各类机制提供给它的 PodSpecs, 确保这些 PodSpecs 中描述的容器处于运行状态且健康。 kubelet 不会管理不是由 Kubernetes 创建的容器。是单独的程序,在宿主机上运行的kube-proxy(单独的进程)​ kube-proxy是集群中每个节点(node)上所运行的网络代理, 实现 Kubernetes 服务(Service) 概念的一部分。​ kube-proxy 维护节点上的一些网络规则, 这些网络规则会允许从集群内部或外部的网络会话与 Pod 进行网络通信。(控制数据的进出)(负载均衡)​ 如果操作系统提供了可用的数据包过滤层,则 kube-proxy 会通过它来实现网络规则。 否则,kube-proxy 仅做流量转发。容器运行时(Container Runtime)​ 容器运行环境是负责运行容器的软件。​ Kubernetes 支持许多容器运行环境,例如 containerd、 CRI-O以及 Kubernetes CRI (容器运行环境接口)的其他任何实现.
0
0
0
浏览量2015
锅从天上来

【Kubernetes】可视化UI界面Dashboard

一、安装Dashboard1.1、上传镜像并解压将课件中的镜像上传到工作节点,我的工作节点是node01和node02。然后手动解压。docker load -i dashboard_2_0_0.tar.gz docker load -i metrics-scrapter-1-0-1.tar.gz1.2、安装dashboard组件上传kubernetes-dashboard.yaml文件并执行。文件内容如下:# Copyright 2017 The Kubernetes Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. apiVersion: v1 kind: Namespace metadata: name: kubernetes-dashboard --- apiVersion: v1 kind: ServiceAccount metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard namespace: kubernetes-dashboard --- kind: Service apiVersion: v1 metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard namespace: kubernetes-dashboard spec: ports: - port: 443 targetPort: 8443 selector: k8s-app: kubernetes-dashboard --- apiVersion: v1 kind: Secret metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard-certs namespace: kubernetes-dashboard type: Opaque --- apiVersion: v1 kind: Secret metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard-csrf namespace: kubernetes-dashboard type: Opaque data: csrf: "" --- apiVersion: v1 kind: Secret metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard-key-holder namespace: kubernetes-dashboard type: Opaque --- kind: ConfigMap apiVersion: v1 metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard-settings namespace: kubernetes-dashboard --- kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard namespace: kubernetes-dashboard rules: # Allow Dashboard to get, update and delete Dashboard exclusive secrets. - apiGroups: [""] resources: ["secrets"] resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs", "kubernetes-dashboard-csrf"] verbs: ["get", "update", "delete"] # Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map. - apiGroups: [""] resources: ["configmaps"] resourceNames: ["kubernetes-dashboard-settings"] verbs: ["get", "update"] # Allow Dashboard to get metrics. - apiGroups: [""] resources: ["services"] resourceNames: ["heapster", "dashboard-metrics-scraper"] verbs: ["proxy"] - apiGroups: [""] resources: ["services/proxy"] resourceNames: ["heapster", "http:heapster:", "https:heapster:", "dashboard-metrics-scraper", "http:dashboard-metrics-scraper"] verbs: ["get"] --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard rules: # Allow Metrics Scraper to get metrics from the Metrics server - apiGroups: ["metrics.k8s.io"] resources: ["pods", "nodes"] verbs: ["get", "list", "watch"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard namespace: kubernetes-dashboard roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: kubernetes-dashboard subjects: - kind: ServiceAccount name: kubernetes-dashboard namespace: kubernetes-dashboard --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: kubernetes-dashboard roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: kubernetes-dashboard subjects: - kind: ServiceAccount name: kubernetes-dashboard namespace: kubernetes-dashboard --- kind: Deployment apiVersion: apps/v1 metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard namespace: kubernetes-dashboard spec: replicas: 1 revisionHistoryLimit: 10 selector: matchLabels: k8s-app: kubernetes-dashboard template: metadata: labels: k8s-app: kubernetes-dashboard spec: containers: - name: kubernetes-dashboard image: kubernetesui/dashboard:v2.0.0-beta8 imagePullPolicy: IfNotPresent ports: - containerPort: 8443 protocol: TCP args: - --auto-generate-certificates - --namespace=kubernetes-dashboard # Uncomment the following line to manually specify Kubernetes API server Host # If not specified, Dashboard will attempt to auto discover the API server and connect # to it. Uncomment only if the default does not work. # - --apiserver-host=http://my-address:port volumeMounts: - name: kubernetes-dashboard-certs mountPath: /certs # Create on-disk volume to store exec logs - mountPath: /tmp name: tmp-volume livenessProbe: httpGet: scheme: HTTPS path: / port: 8443 initialDelaySeconds: 30 timeoutSeconds: 30 securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true runAsUser: 1001 runAsGroup: 2001 volumes: - name: kubernetes-dashboard-certs secret: secretName: kubernetes-dashboard-certs - name: tmp-volume emptyDir: {} serviceAccountName: kubernetes-dashboard nodeSelector: "beta.kubernetes.io/os": linux # Comment the following tolerations if Dashboard must not be deployed on master tolerations: - key: node-role.kubernetes.io/master effect: NoSchedule --- kind: Service apiVersion: v1 metadata: labels: k8s-app: dashboard-metrics-scraper name: dashboard-metrics-scraper namespace: kubernetes-dashboard spec: ports: - port: 8000 targetPort: 8000 selector: k8s-app: dashboard-metrics-scraper --- kind: Deployment apiVersion: apps/v1 metadata: labels: k8s-app: dashboard-metrics-scraper name: dashboard-metrics-scraper namespace: kubernetes-dashboard spec: replicas: 1 revisionHistoryLimit: 10 selector: matchLabels: k8s-app: dashboard-metrics-scraper template: metadata: labels: k8s-app: dashboard-metrics-scraper annotations: seccomp.security.alpha.kubernetes.io/pod: 'runtime/default' spec: containers: - name: dashboard-metrics-scraper image: kubernetesui/metrics-scraper:v1.0.1 imagePullPolicy: IfNotPresent ports: - containerPort: 8000 protocol: TCP livenessProbe: httpGet: scheme: HTTP path: / port: 8000 initialDelaySeconds: 30 timeoutSeconds: 30 volumeMounts: - mountPath: /tmp name: tmp-volume securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true runAsUser: 1001 runAsGroup: 2001 serviceAccountName: kubernetes-dashboard nodeSelector: "beta.kubernetes.io/os": linux # Comment the following tolerations if Dashboard must not be deployed on master tolerations: - key: node-role.kubernetes.io/master effect: NoSchedule volumes: - name: tmp-volume emptyDir: {}kubectl apply -f kubernetes-dashboard.yamlkubectl get pods -n kubernetes-dashboard显示结果如下,代表安装成功:[root@master dashboard]# kubectl apply -f kubernetes-dashboard.yaml namespace/kubernetes-dashboard created serviceaccount/kubernetes-dashboard created service/kubernetes-dashboard created secret/kubernetes-dashboard-certs created secret/kubernetes-dashboard-csrf created secret/kubernetes-dashboard-key-holder created configmap/kubernetes-dashboard-settings created role.rbac.authorization.k8s.io/kubernetes-dashboard created clusterrole.rbac.authorization.k8s.io/kubernetes-dashboard created rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created clusterrolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created deployment.apps/kubernetes-dashboard created service/dashboard-metrics-scraper created deployment.apps/dashboard-metrics-scraper created [root@master dashboard]# kubectl get pods -n kubernetes-dashboard NAME READY STATUS RESTARTS AGE dashboard-metrics-scraper-778b77d469-np56t 1/1 Running 0 5s kubernetes-dashboard-86899d4bc7-7tll9 1/1 Running 0 5s1.3、修改service# 查看dashboard前端的service [root@master dashboard]# kubectl get svc -n kubernetes-dashboard NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE dashboard-metrics-scraper ClusterIP 10.1.91.83 <none> 8000/TCP 3m27s kubernetes-dashboard ClusterIP 10.1.135.105 <none> 443/TCP 3m27s # 修改service type类型变成NodePort [root@master dashboard]# kubectl edit svc kubernetes-dashboard -n kubernetes-dashboard service/kubernetes-dashboard edited [root@master dashboard]# kubectl get svc -n kubernetes-dashboard NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE dashboard-metrics-scraper ClusterIP 10.1.91.83 <none> 8000/TCP 4m50s kubernetes-dashboard NodePort 10.1.135.105 <none> 443:32291/TCP 4m50s1.4、访问dashboard上面可看到service类型是NodePort,访问任何一个工作节点ip: 32291端口即可访问kubernetes dashboard,在浏览器(使用火狐浏览器)访问如下地址:https://10.32.1.147:32291/二、通过Token令牌访问Dashboard2.1、创建clusterrolebinding创建管理员token,具有查看任何空间的权限,可以管理所有资源对象# 创建 ClusterRoleBinding,名称为dashboard-cluster-admin # 将Kubernetes Dashboard 的 ServiceAccount (kubernetes-dashboard名称空间下的kubernetes-dashboard这个sa)分配给集群角色 cluster-admin # 目的:赋予 Dashboard 访问和管理整个集群的权限 [root@master dashboard]# kubectl create clusterrolebinding dashboard-cluster-admin --clusterrole=cluster-admin --serviceaccount=kubernetes-dashboard:kubernetes-dashboard clusterrolebinding.rbac.authorization.k8s.io/dashboard-cluster-admin created2.2、获取token找到带有token的kubernetes-dashboard-token-dxqqq[root@master dashboard]# kubectl get secret -n kubernetes-dashboard NAME TYPE DATA AGE default-token-96j7l kubernetes.io/service-account-token 3 14m kubernetes-dashboard-certs Opaque 0 14m kubernetes-dashboard-csrf Opaque 1 14m kubernetes-dashboard-key-holder Opaque 2 14m kubernetes-dashboard-token-dxqqq kubernetes.io/service-account-token 3 14m [root@master dashboard]# kubectl describe secret kubernetes-dashboard-token-dxqqq -n kubernetes-dashboard Name: kubernetes-dashboard-token-dxqqq Namespace: kubernetes-dashboard Labels: <none> Annotations: kubernetes.io/service-account.name: kubernetes-dashboard kubernetes.io/service-account.uid: 0f371d4a-899d-4f83-9980-cdc1894b0ebc Type: kubernetes.io/service-account-token Data ==== ca.crt: 1066 bytes namespace: 20 bytes token: eyJhbGciOiJSUzI1NiIsImtpZCI6IjNQeTlIRF96Rk4yV09iSC1FNG4zeGR0X19VQThPSlNlbEpUeTlfcDRpakUifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJrdWJlcm5ldGVzLWRhc2hib2FyZC10b2tlbi1keHFxcSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjBmMzcxZDRhLTg5OWQtNGY4My05OTgwLWNkYzE4OTRiMGViYyIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlcm5ldGVzLWRhc2hib2FyZDprdWJlcm5ldGVzLWRhc2hib2FyZCJ9.jjn9uz-DKUWxS9qfB41rnUoyk0SVtODBW5y8NEskhElU0KSMj487kc3yBbPLqNQPUgrmA27JK_M9PvYwrUJfLZfxkLtr7cquXXmrUcqXrt3Vr-BkNaExAiUFPYYLXPlUAB8J3lGnY4f1J_dxkxLR-OcyEiC--5eOtUKia1WhrENEwQH1Me4iKcWJSOvJeq7fisgLDVGIjHbg3Iz7PaRHWC5TZ5W-05BkuxtScZDwFS7MItfFicfkGM_SFEEQ5Mg_mDoNArJwP_16quG79eei17n7Av73e41CO7fmyk4fMpnyn-oFfa447D9qWBNbI86ou4Z4B-8GP3Lf4ZyyLnJm9w2.3、使用token登录记住token后面的值,把下面的token值复制到浏览器token登陆处即可登陆点击sing in登陆,显示如下,这次就可以看到和操作任何名称空间的资源了三、通过kubeconfig文件访问Dashboard3.1、创建cluster集群[root@master dashboard]# cd /etc/kubernetes/pki [root@master pki]# kubectl config set-cluster kubernetes --certificate-authority=./ca.crt --server="https://10。32.1.147:6443" --embed-certs=true --kubeconfig=/root/dashboard-admin.conf Cluster "kubernetes" set. [root@master pki]# cat /root/dashboard-admin.conf apiVersion: v1 clusters: - cluster: certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM1ekNDQWMrZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJek1ETXdOakE1TVRNMU1sb1hEVE16TURNd016QTVNVE0xTWxvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTmVnCmNFYUZuTkNVd0hrT3ltOHQ2MlRsUmtxb1VvT1pzdFpIbjdWK3g4dnQxVlR2SldaRkV3YXphNGU1M0FxQUNVaHQKeDVyZksvcGN3T01yR085dk95TU9EMFkza1NYWVR1TDBpUVloRlNZMDVaT0tUdkI3UG5Wb3BueURqRXVBMU80Tgp2TFowZ1RVaWhoMTg2WEtQaGV2T2djMjErU2d5TCtXOHgxQjFoYWtFWFFGc3U2a3ZvWGFnMUU4VVQ2TjZUejJECkJ5MHRqQjNBU3ZuV3hzRHNiSmpLVytIbGhkL2c4dlBURFd5S24rQkdWeWMyb1A1Zkk1T0ZYR0NlVkVTWHUvb0IKNDNsOGQ1SHBvdUY4OTJhRmJjRWc3T0gvTVliS0REOXdYdEdQNXN2a1NNd2x4Z3Y1RUh6MjBKRzNXWlNtQjdFQgpxTHljQzJPeEdiVndQWDIwMGZrQ0F3RUFBYU5DTUVBd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZCNW00N2V0aEErRkhmZ3orZVhtM0pZSkJwNmVNQTBHQ1NxR1NJYjMKRFFFQkN3VUFBNElCQVFCdlgxWDEra3RZMHFaeEJQNjgvZjZoVlRFVENSdFBmdHluZnJnY0JOcWtDdzhod2M4UgoyMzAyNmM4NVFFbFU4TkdvR09uSGVCWHlSOERTZE4rNndTL1g5aEw5UU9VQTYwNk1aNG9qaktJUE1LQThCNVdDCndrM1llWkFRakhPcmxPTGNUVzNkL0pRSEQ5ZWFNejB3RnI5QmV5eDdwajhlT0FaU0tPT1dLanU4VlB5aUxvK2YKdzRtbXo0OGtzWHNhcGVRZzNHMWFtNi9CT3VzWmxUNHVyc1JxVUhFU1lzaGRFT29MUTRmanoyTml3eEc1VVFMVApTWXg2VE9mSGRRdTFFSENHNzBud0NNU0VMZVZzN2gyc2FQd1g2Rk9XTzg0UUxheXF4bW1YSVY0eGFUeitIUUhtClJ5SURXMm9zWnVYZEVieXNNZ0NFcWRSeklyR0Fjam9ZdlBmOAotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== server: https://10.32.1.147:6443 name: kubernetes contexts: null current-context: "" kind: Config preferences: {} users: null3.2、创建credentials创建credentials需要使用上面的kubernetes-dashboard-token-dxqqq对应的token信息[root@master pki]# DEF_NS_ADMIN_TOKEN=$(kubectl get secret kubernetes-dashboard-token-dxqqq -n kubernetes-dashboard -o jsonpath={.data.token}|base64 -d) [root@master pki]# kubectl config set-credentials dashboard-admin --token=$DEF_NS_ADMIN_TOKEN --kubeconfig=/root/dashboard-admin.conf User "dashboard-admin" set.[root@master pki]# cat /root/dashboard-admin.conf apiVersion: v1 clusters: - cluster: certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM1ekNDQWMrZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJek1ETXdOakE1TVRNMU1sb1hEVE16TURNd016QTVNVE0xTWxvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTmVnCmNFYUZuTkNVd0hrT3ltOHQ2MlRsUmtxb1VvT1pzdFpIbjdWK3g4dnQxVlR2SldaRkV3YXphNGU1M0FxQUNVaHQKeDVyZksvcGN3T01yR085dk95TU9EMFkza1NYWVR1TDBpUVloRlNZMDVaT0tUdkI3UG5Wb3BueURqRXVBMU80Tgp2TFowZ1RVaWhoMTg2WEtQaGV2T2djMjErU2d5TCtXOHgxQjFoYWtFWFFGc3U2a3ZvWGFnMUU4VVQ2TjZUejJECkJ5MHRqQjNBU3ZuV3hzRHNiSmpLVytIbGhkL2c4dlBURFd5S24rQkdWeWMyb1A1Zkk1T0ZYR0NlVkVTWHUvb0IKNDNsOGQ1SHBvdUY4OTJhRmJjRWc3T0gvTVliS0REOXdYdEdQNXN2a1NNd2x4Z3Y1RUh6MjBKRzNXWlNtQjdFQgpxTHljQzJPeEdiVndQWDIwMGZrQ0F3RUFBYU5DTUVBd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZCNW00N2V0aEErRkhmZ3orZVhtM0pZSkJwNmVNQTBHQ1NxR1NJYjMKRFFFQkN3VUFBNElCQVFCdlgxWDEra3RZMHFaeEJQNjgvZjZoVlRFVENSdFBmdHluZnJnY0JOcWtDdzhod2M4UgoyMzAyNmM4NVFFbFU4TkdvR09uSGVCWHlSOERTZE4rNndTL1g5aEw5UU9VQTYwNk1aNG9qaktJUE1LQThCNVdDCndrM1llWkFRakhPcmxPTGNUVzNkL0pRSEQ5ZWFNejB3RnI5QmV5eDdwajhlT0FaU0tPT1dLanU4VlB5aUxvK2YKdzRtbXo0OGtzWHNhcGVRZzNHMWFtNi9CT3VzWmxUNHVyc1JxVUhFU1lzaGRFT29MUTRmanoyTml3eEc1VVFMVApTWXg2VE9mSGRRdTFFSENHNzBud0NNU0VMZVZzN2gyc2FQd1g2Rk9XTzg0UUxheXF4bW1YSVY0eGFUeitIUUhtClJ5SURXMm9zWnVYZEVieXNNZ0NFcWRSeklyR0Fjam9ZdlBmOAotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== server: https://10.32.1.147:6443 name: kubernetes contexts: null current-context: "" kind: Config preferences: {} users: - name: dashboard-admin user: token: eyJhbGciOiJSUzI1NiIsImtpZCI6IjNQeTlIRF96Rk4yV09iSC1FNG4zeGR0X19VQThPSlNlbEpUeTlfcDRpakUifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJrdWJlcm5ldGVzLWRhc2hib2FyZC10b2tlbi1keHFxcSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjBmMzcxZDRhLTg5OWQtNGY4My05OTgwLWNkYzE4OTRiMGViYyIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlcm5ldGVzLWRhc2hib2FyZDprdWJlcm5ldGVzLWRhc2hib2FyZCJ9.jjn9uz-DKUWxS9qfB41rnUoyk0SVtODBW5y8NEskhElU0KSMj487kc3yBbPLqNQPUgrmA27JK_M9PvYwrUJfLZfxkLtr7cquXXmrUcqXrt3Vr-BkNaExAiUFPYYLXPlUAB8J3lGnY4f1J_dxkxLR-OcyEiC--5eOtUKia1WhrENEwQH1Me4iKcWJSOvJeq7fisgLDVGIjHbg3Iz7PaRHWC5TZ5W-05BkuxtScZDwFS7MItfFicfkGM_SFEEQ5Mg_mDoNArJwP_16quG79eei17n7Av73e41CO7fmyk4fMpnyn-oFfa447D9qWBNbI86ou4Z4B-8GP3Lf4ZyyLnJm9w3.3、创建context[root@master pki]# kubectl config set-context dashboard-admin@kubernetes --cluster=kubernetes --user=dashboard-admin --kubeconfig=/root/dashboard-admin.conf Context "dashboard-admin@kubernetes" created. [root@master pki]# cat /root/dashboard-admin.conf apiVersion: v1 clusters: - cluster: certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM1ekNDQWMrZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJek1ETXdOakE1TVRNMU1sb1hEVE16TURNd016QTVNVE0xTWxvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTmVnCmNFYUZuTkNVd0hrT3ltOHQ2MlRsUmtxb1VvT1pzdFpIbjdWK3g4dnQxVlR2SldaRkV3YXphNGU1M0FxQUNVaHQKeDVyZksvcGN3T01yR085dk95TU9EMFkza1NYWVR1TDBpUVloRlNZMDVaT0tUdkI3UG5Wb3BueURqRXVBMU80Tgp2TFowZ1RVaWhoMTg2WEtQaGV2T2djMjErU2d5TCtXOHgxQjFoYWtFWFFGc3U2a3ZvWGFnMUU4VVQ2TjZUejJECkJ5MHRqQjNBU3ZuV3hzRHNiSmpLVytIbGhkL2c4dlBURFd5S24rQkdWeWMyb1A1Zkk1T0ZYR0NlVkVTWHUvb0IKNDNsOGQ1SHBvdUY4OTJhRmJjRWc3T0gvTVliS0REOXdYdEdQNXN2a1NNd2x4Z3Y1RUh6MjBKRzNXWlNtQjdFQgpxTHljQzJPeEdiVndQWDIwMGZrQ0F3RUFBYU5DTUVBd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZCNW00N2V0aEErRkhmZ3orZVhtM0pZSkJwNmVNQTBHQ1NxR1NJYjMKRFFFQkN3VUFBNElCQVFCdlgxWDEra3RZMHFaeEJQNjgvZjZoVlRFVENSdFBmdHluZnJnY0JOcWtDdzhod2M4UgoyMzAyNmM4NVFFbFU4TkdvR09uSGVCWHlSOERTZE4rNndTL1g5aEw5UU9VQTYwNk1aNG9qaktJUE1LQThCNVdDCndrM1llWkFRakhPcmxPTGNUVzNkL0pRSEQ5ZWFNejB3RnI5QmV5eDdwajhlT0FaU0tPT1dLanU4VlB5aUxvK2YKdzRtbXo0OGtzWHNhcGVRZzNHMWFtNi9CT3VzWmxUNHVyc1JxVUhFU1lzaGRFT29MUTRmanoyTml3eEc1VVFMVApTWXg2VE9mSGRRdTFFSENHNzBud0NNU0VMZVZzN2gyc2FQd1g2Rk9XTzg0UUxheXF4bW1YSVY0eGFUeitIUUhtClJ5SURXMm9zWnVYZEVieXNNZ0NFcWRSeklyR0Fjam9ZdlBmOAotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== server: https://10.32.1.147:6443 name: kubernetes contexts: null current-context: "" kind: Config preferences: {} users: - name: dashboard-admin user: token: eyJhbGciOiJSUzI1NiIsImtpZCI6IjNQeTlIRF96Rk4yV09iSC1FNG4zeGR0X19VQThPSlNlbEpUeTlfcDRpakUifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJrdWJlcm5ldGVzLWRhc2hib2FyZC10b2tlbi1keHFxcSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjBmMzcxZDRhLTg5OWQtNGY4My05OTgwLWNkYzE4OTRiMGViYyIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlcm5ldGVzLWRhc2hib2FyZDprdWJlcm5ldGVzLWRhc2hib2FyZCJ9.jjn9uz-DKUWxS9qfB41rnUoyk0SVtODBW5y8NEskhElU0KSMj487kc3yBbPLqNQPUgrmA27JK_M9PvYwrUJfLZfxkLtr7cquXXmrUcqXrt3Vr-BkNaExAiUFPYYLXPlUAB8J3lGnY4f1J_dxkxLR-OcyEiC--5eOtUKia1WhrENEwQH1Me4iKcWJSOvJeq7fisgLDVGIjHbg3Iz7PaRHWC5TZ5W-05BkuxtScZDwFS7MItfFicfkGM_SFEEQ5Mg_mDoNArJwP_16quG79eei17n7Av73e41CO7fmyk4fMpnyn-oFfa447D9qWBNbI86ou4Z4B-8GP3Lf4ZyyLnJm9w [root@master pki]# kubectl config set-context dashboard-admin@kubernetes --cluster=kubernetes --user=dashboard-admin --kubeconfig=/root/dashboard-admin.conf Context "dashboard-admin@kubernetes" created. [root@master pki]# cat /root/dashboard-admin.conf apiVersion: v1 clusters: - cluster: certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM1ekNDQWMrZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJek1ETXdOakE1TVRNMU1sb1hEVE16TURNd016QTVNVE0xTWxvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTmVnCmNFYUZuTkNVd0hrT3ltOHQ2MlRsUmtxb1VvT1pzdFpIbjdWK3g4dnQxVlR2SldaRkV3YXphNGU1M0FxQUNVaHQKeDVyZksvcGN3T01yR085dk95TU9EMFkza1NYWVR1TDBpUVloRlNZMDVaT0tUdkI3UG5Wb3BueURqRXVBMU80Tgp2TFowZ1RVaWhoMTg2WEtQaGV2T2djMjErU2d5TCtXOHgxQjFoYWtFWFFGc3U2a3ZvWGFnMUU4VVQ2TjZUejJECkJ5MHRqQjNBU3ZuV3hzRHNiSmpLVytIbGhkL2c4dlBURFd5S24rQkdWeWMyb1A1Zkk1T0ZYR0NlVkVTWHUvb0IKNDNsOGQ1SHBvdUY4OTJhRmJjRWc3T0gvTVliS0REOXdYdEdQNXN2a1NNd2x4Z3Y1RUh6MjBKRzNXWlNtQjdFQgpxTHljQzJPeEdiVndQWDIwMGZrQ0F3RUFBYU5DTUVBd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZCNW00N2V0aEErRkhmZ3orZVhtM0pZSkJwNmVNQTBHQ1NxR1NJYjMKRFFFQkN3VUFBNElCQVFCdlgxWDEra3RZMHFaeEJQNjgvZjZoVlRFVENSdFBmdHluZnJnY0JOcWtDdzhod2M4UgoyMzAyNmM4NVFFbFU4TkdvR09uSGVCWHlSOERTZE4rNndTL1g5aEw5UU9VQTYwNk1aNG9qaktJUE1LQThCNVdDCndrM1llWkFRakhPcmxPTGNUVzNkL0pRSEQ5ZWFNejB3RnI5QmV5eDdwajhlT0FaU0tPT1dLanU4VlB5aUxvK2YKdzRtbXo0OGtzWHNhcGVRZzNHMWFtNi9CT3VzWmxUNHVyc1JxVUhFU1lzaGRFT29MUTRmanoyTml3eEc1VVFMVApTWXg2VE9mSGRRdTFFSENHNzBud0NNU0VMZVZzN2gyc2FQd1g2Rk9XTzg0UUxheXF4bW1YSVY0eGFUeitIUUhtClJ5SURXMm9zWnVYZEVieXNNZ0NFcWRSeklyR0Fjam9ZdlBmOAotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== server: https://10.32.1.147:6443 name: kubernetes contexts: - context: cluster: kubernetes user: dashboard-admin name: dashboard-admin@kubernetes current-context: "" kind: Config preferences: {} users: - name: dashboard-admin user: token: eyJhbGciOiJSUzI1NiIsImtpZCI6IjNQeTlIRF96Rk4yV09iSC1FNG4zeGR0X19VQThPSlNlbEpUeTlfcDRpakUifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJrdWJlcm5ldGVzLWRhc2hib2FyZC10b2tlbi1keHFxcSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjBmMzcxZDRhLTg5OWQtNGY4My05OTgwLWNkYzE4OTRiMGViYyIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlcm5ldGVzLWRhc2hib2FyZDprdWJlcm5ldGVzLWRhc2hib2FyZCJ9.jjn9uz-DKUWxS9qfB41rnUoyk0SVtODBW5y8NEskhElU0KSMj487kc3yBbPLqNQPUgrmA27JK_M9PvYwrUJfLZfxkLtr7cquXXmrUcqXrt3Vr-BkNaExAiUFPYYLXPlUAB8J3lGnY4f1J_dxkxLR-OcyEiC--5eOtUKia1WhrENEwQH1Me4iKcWJSOvJeq7fisgLDVGIjHbg3Iz7PaRHWC5TZ5W-05BkuxtScZDwFS7MItfFicfkGM_SFEEQ5Mg_mDoNArJwP_16quG79eei17n7Av73e41CO7fmyk4fMpnyn-oFfa447D9qWBNbI86ou4Z4B-8GP3Lf4ZyyLnJm9w3.4、切换context切换context的current-context是dashboard-admin@kubernetes[root@master pki]# kubectl config use-context dashboard-admin@kubernetes --kubeconfig=/root/dashboard-admin.conf Switched to context "dashboard-admin@kubernetes".将/root/dashboard-admin.conf文件下载下来[root@master pki]# cat /root/dashboard-admin.conf apiVersion: v1 clusters: - cluster: certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM1ekNDQWMrZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJek1ETXdOakE1TVRNMU1sb1hEVE16TURNd016QTVNVE0xTWxvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTmVnCmNFYUZuTkNVd0hrT3ltOHQ2MlRsUmtxb1VvT1pzdFpIbjdWK3g4dnQxVlR2SldaRkV3YXphNGU1M0FxQUNVaHQKeDVyZksvcGN3T01yR085dk95TU9EMFkza1NYWVR1TDBpUVloRlNZMDVaT0tUdkI3UG5Wb3BueURqRXVBMU80Tgp2TFowZ1RVaWhoMTg2WEtQaGV2T2djMjErU2d5TCtXOHgxQjFoYWtFWFFGc3U2a3ZvWGFnMUU4VVQ2TjZUejJECkJ5MHRqQjNBU3ZuV3hzRHNiSmpLVytIbGhkL2c4dlBURFd5S24rQkdWeWMyb1A1Zkk1T0ZYR0NlVkVTWHUvb0IKNDNsOGQ1SHBvdUY4OTJhRmJjRWc3T0gvTVliS0REOXdYdEdQNXN2a1NNd2x4Z3Y1RUh6MjBKRzNXWlNtQjdFQgpxTHljQzJPeEdiVndQWDIwMGZrQ0F3RUFBYU5DTUVBd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZCNW00N2V0aEErRkhmZ3orZVhtM0pZSkJwNmVNQTBHQ1NxR1NJYjMKRFFFQkN3VUFBNElCQVFCdlgxWDEra3RZMHFaeEJQNjgvZjZoVlRFVENSdFBmdHluZnJnY0JOcWtDdzhod2M4UgoyMzAyNmM4NVFFbFU4TkdvR09uSGVCWHlSOERTZE4rNndTL1g5aEw5UU9VQTYwNk1aNG9qaktJUE1LQThCNVdDCndrM1llWkFRakhPcmxPTGNUVzNkL0pRSEQ5ZWFNejB3RnI5QmV5eDdwajhlT0FaU0tPT1dLanU4VlB5aUxvK2YKdzRtbXo0OGtzWHNhcGVRZzNHMWFtNi9CT3VzWmxUNHVyc1JxVUhFU1lzaGRFT29MUTRmanoyTml3eEc1VVFMVApTWXg2VE9mSGRRdTFFSENHNzBud0NNU0VMZVZzN2gyc2FQd1g2Rk9XTzg0UUxheXF4bW1YSVY0eGFUeitIUUhtClJ5SURXMm9zWnVYZEVieXNNZ0NFcWRSeklyR0Fjam9ZdlBmOAotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== server: https://10.32.1.147:6443 name: kubernetes contexts: - context: cluster: kubernetes user: dashboard-admin name: dashboard-admin@kubernetes current-context: dashboard-admin@kubernetes kind: Config preferences: {} users: - name: dashboard-admin user: token: eyJhbGciOiJSUzI1NiIsImtpZCI6IjNQeTlIRF96Rk4yV09iSC1FNG4zeGR0X19VQThPSlNlbEpUeTlfcDRpakUifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJrdWJlcm5ldGVzLWRhc2hib2FyZC10b2tlbi1keHFxcSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjBmMzcxZDRhLTg5OWQtNGY4My05OTgwLWNkYzE4OTRiMGViYyIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlcm5ldGVzLWRhc2hib2FyZDprdWJlcm5ldGVzLWRhc2hib2FyZCJ9.jjn9uz-DKUWxS9qfB41rnUoyk0SVtODBW5y8NEskhElU0KSMj487kc3yBbPLqNQPUgrmA27JK_M9PvYwrUJfLZfxkLtr7cquXXmrUcqXrt3Vr-BkNaExAiUFPYYLXPlUAB8J3lGnY4f1J_dxkxLR-OcyEiC--5eOtUKia1WhrENEwQH1Me4iKcWJSOvJeq7fisgLDVGIjHbg3Iz7PaRHWC5TZ5W-05BkuxtScZDwFS7MItfFicfkGM_SFEEQ5Mg_mDoNArJwP_16quG79eei17n7Av73e41CO7fmyk4fMpnyn-oFfa447D9qWBNbI86ou4Z4B-8GP3Lf4ZyyLnJm9w3.5、导入dashboard-admin.conf文件四、通过kubernetes-dashboard创建容器点开右上角红色箭头标注的 “+”,如下图所示:选择Create from form注:表单中创建pod时没有创建nodeport的选项,会自动创建在30000+以上的端口。上面箭头标注的地方填写之后点击Deploy即可完成Pod的创建,如下访问:http://10.32.1.147:32282/关于port、targetport、nodeport的说明:nodeport是集群外流量访问集群内服务的端口,比如客户访问nginx,apache,port是集群内的pod互相通信用的端口类型,比如nginx访问mysql,而mysql是不需要让客户访问到的,port是service的的端口targetport目标端口,也就是最终端口,也就是pod的端口。
0
0
0
浏览量2062
锅从天上来

【Kubernetes】配置管理中心Configmap

一、简介1.1、什么是ConfigmapConfigmap是k8s中的资源对象,用于保存非机密性的配置的,数据可以用key/value键值对的形式保存,也可通过文件的形式保存。1.2、Configmap能解决什么问题我们在部署服务的时候,每个服务都有自己的配置文件,如果一台服务器上部署多个服务:nginx、tomcat、apache等,那么这些配置都存在这个节点上,假如一台服务器不能满足线上高并发的要求,需要对服务器扩容,扩容之后的服务器还是需要部署多个服务:nginx、tomcat、apache,新增加的服务器上还是要管理这些服务的配置,如果有一个服务出现问题,需要修改配置文件,每台物理节点上的配置都需要修改,这种方式肯定满足不了线上大批量的配置变更要求。所以,k8s中引入了Configmap资源对象,可以当成volume挂载到pod中,实现统一的配置管理。1、Configmap是k8s中的资源, 相当于配置文件,可以有一个或者多个Configmap;2、Configmap可以做成Volume,k8s pod启动之后,通过 volume 形式映射到容器内部指定目录上;3、容器中应用程序按照原有方式读取容器特定目录上的配置文件。4、在容器看来,配置文件就像是打包在容器内部特定目录,整个过程对应用没有任何侵入。1.3、Configmap应用场景1、 使用k8s部署应用,当你将应用配置写进代码中,更新配置时也需要打包镜像。configmap可以将配置信息和docker镜像解耦,以便实现镜像的可移植性和可复用性,因为一个configMap其实就是一系列配置信息的集合,可直接注入到Pod中给容器使用。configmap注入方式有两种,一种将configMap做为存储卷,一种是将configMap通过env中configMapKeyRef注入到容器中。2、使用微服务架构的话,存在多个服务共用配置的情况,如果每个服务中单独一份配置的话,那么更新配置就很麻烦, 使用configmap可以友好的进行配置共享。1.4、Configmap局限性ConfigMap在设计上不是用来保存大量数据的。在ConfigMap中保存的数据不可超过1 MiB。如果你需要保存超出此尺寸限制的数据,可以考虑挂载存储卷或者使用独立的数据库或者文件服务。二、Configmap创建方法2.1、命令行直接创建直接在命令行中指定configmap参数创建,通过–from-literal指定参数[root@master ~]# kubectl create configmap tomcat-config --from-literal=tomcat_port=8080 --from-literal=server_name=myapp.tomcat.com configmap/tomcat-config created [root@master ~]# kubectl describe configmap tomcat-config Name: tomcat-config Namespace: default Labels: <none> Annotations: <none> Data ==== server_name: ---- myapp.tomcat.com tomcat_port: ---- 8080 BinaryData ==== Events: <none>2.2、通过文件创建通过指定文件创建一个configmap,–from-file=<文件>[root@master 14]# cat nginx.conf server { server_name www.nginx.com; listen 80; root /home/nginx/www/ } # 定义一个key是www,值是nginx.conf中的内容 [root@master 14]# kubectl create configmap www-nginx --from-file=www=./nginx.conf configmap/www-nginx created [root@master 14]# kubectl describe configmap www-nginx Name: www-nginx Namespace: default Labels: <none> Annotations: <none> Data ==== www: ---- server { server_name www.nginx.com; listen 80; root /home/nginx/www/ } BinaryData ==== Events: <none>2.3、指定目录创建[root@master 14]# mkdir test-a [root@master 14]# cd test-a/ [root@master test-a]# vim my-server.cnf [root@master test-a]# vim my-slave.cnf [root@master test-a]# cat my-server.cnf server-id=1 [root@master test-a]# cat my-slave.cnf server-id=2# 指定目录创建configmap [root@master test-a]# kubectl create configmap mysql-config --from-file=/root/CKA/model2/14/test-a configmap/mysql-config created [root@master test-a]# kubectl describe configmap mysql-config Name: mysql-config Namespace: default Labels: <none> Annotations: <none> Data ==== my-server.cnf: ---- server-id=1 my-slave.cnf: ---- server-id=2 BinaryData ==== Events: <none>2.4、编写configmap资源清单yaml文件[root@master 14]# cat mysql-configmap.yaml apiVersion: v1 kind: ConfigMap metadata: name: mysql labels: app: mysql data: master.cnf: | [mysqld] log-bin log_bin_trust_function_creators=1 lower_case_table_names=1 slave.cnf: | [mysqld] super-read-only log_bin_trust_function_creators=1 [root@master 14]# kubectl apply -f mysql-configmap.yaml configmap/mysql created [root@master 14]# kubectl describe configmap mysql Name: mysql Namespace: default Labels: app=mysql Annotations: <none> Data ==== master.cnf: ---- [mysqld] log-bin log_bin_trust_function_creators=1 lower_case_table_names=1 slave.cnf: ---- [mysqld] super-read-only log_bin_trust_function_creators=1 BinaryData ==== Events: <none>三、使用Configmap3.1、通过环境变量引入:使用configMapKeyRef1、创建一个存储mysql配置的configmap[root@master 14]# cat mysql-configmap.yaml apiVersion: v1 kind: ConfigMap metadata: name: mysql labels: app: mysql data: log: "1" lower: "1" [root@master 14]# kubectl apply -f mysql-configmap.yaml configmap/mysql configured2、创建pod,引用Configmap中的内容[root@master 14]# cat mysql-pod.yaml apiVersion: v1 kind: Pod metadata: name: mysql-pod spec: containers: - name: mysql image: busybox imagePullPolicy: IfNotPresent command: [ "/bin/sh", "-c", "sleep 3600" ] env: - name: log_bin # 定义环境变量log_bin valueFrom: configMapKeyRef: name: mysql # 指定configmap的名字 key: log # 指定configmap中的key - name: lower # 定义环境变量lower valueFrom: configMapKeyRef: name: mysql key: lower restartPolicy: Never [root@master 14]# kubectl apply -f mysql-pod.yaml pod/mysql-pod created [root@master 14]# kubectl exec -it mysql-pod -- /bin/sh / # / # printenv log_bin=1 ... lower=1 ... / #3.2、通过环境变量引入:使用envfrom[root@master 14]# cat mysql-pod-envfrom.yaml apiVersion: v1 kind: Pod metadata: name: mysql-pod-envfrom spec: containers: - name: mysql image: busybox imagePullPolicy: IfNotPresent command: [ "/bin/sh", "-c", "sleep 3600" ] envFrom: - configMapRef: name: mysql #指定configmap的名字 restartPolicy: Never [root@master 14]# kubectl apply -f mysql-pod-envfrom.yaml pod/mysql-pod-envfrom created [root@master 14]# kubectl exec -it mysql-pod-envfrom -- /bin/sh / # / # printenv ... lower=1 ... log=13.3、把configmap做成volume,挂载到pod[root@master 14]# cat mysql-configmap.yaml apiVersion: v1 kind: ConfigMap metadata: name: mysql labels: app: mysql data: log: "1" lower: "1" my.cnf: | [mysqld] Welcome=xianchao [root@master 14]# kubectl apply -f mysql-configmap.yaml configmap/mysql configured[root@master 14]# cat mysql-pod-volume.yaml apiVersion: v1 kind: Pod metadata: name: mysql-pod-volume spec: containers: - name: mysql image: busybox command: [ "/bin/sh","-c","sleep 3600" ] volumeMounts: - name: mysql-config mountPath: /tmp/config volumes: - name: mysql-config configMap: name: mysql restartPolicy: Never [root@master 14]# kubectl apply -f mysql-pod-volume.yaml pod/mysql-pod-volume created [root@master 14]# kubectl exec -it mysql-pod-volume -- /bin/sh / # / # cd /tmp/config/ /tmp/config # ls log lower my.cnf /tmp/config # cat log 1/tmp/config # cat lower /tmp/config # cat my.cnf [mysqld] Welcome=xianchao四、Configmap热更新# 把logs: “1”变成log: “222” [root@master 14]# kubectl edit cm mysql configmap/mysql edited [root@master 14]# k exec -it mysql-pod-volume -c mysql bin/sh kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead. / # / # cd /tmp/config /tmp/config # ls log lower my.cnf /tmp/config # cat log 222/tmp/config #[root@master 14]# k exec -it mysql-pod-envfrom -c mysql /bin/sh kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead. / # / # printenv KUBERNETES_SERVICE_PORT=443 KUBERNETES_PORT=tcp://10.96.0.1:443 HOSTNAME=mysql-pod-envfrom SHLVL=1 HOME=/root TERM=xterm lower=1 KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1 PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin log=1 # 没变注意: 更新 ConfigMap 后:使用该 ConfigMap 挂载的 Env 不会同步更新使用该 ConfigMap 挂载的 Volume 中的数据需要一段时间(实测大概10秒)才能同步更新
0
0
0
浏览量2010
锅从天上来

深入Kubernetes实战系列

涵盖Kubernetes实践的各个方面,包括Dashboard可视化UI界面、高可用集群搭建、四层代理Service、持久化存储与存储类、控制器StatefulSet和DaemonSet、配置管理中心ConfigMap和Secret、认证授权RBAC,以及七层代理Ingress的详细讲解
0
0
0
浏览量2354
锅从天上来

深入Kubernetes实践与原理解析

全面介绍Kubernetes,包括安装部署、核心概念、组件详解、Pod深度解析、命名空间与资源配额、kubectl使用、污点容忍、有状态与无状态应用、Volume和容器探针。
0
0
0
浏览量2173
锅从天上来

【新知实验室 - TRTC 实践】音视频互动 Demo、即时通信 IM 服务搭建

一、TRTC 初识TRTC 是什么TRTC(Tencent RTC)腾讯实时音视频,源自于 QQ 音视频团队,是基于 QQ 音视频多年来的音视频技术积累,位于腾讯云的 RTC 云服务。TRTC 支持腾讯会议、企业微信直播、微信视频号、腾讯云课堂、全民 K 各等业务,是腾讯丰富的音视频场景的最佳实践输出。TRTC 的客户端 SDK 全平台覆盖,有微信/QQ 小程序、企业微信、浏览器,以及 iOS、Windows、Linux 和 macOS 等平台。TRTC 可以旁路到云直播并且通过 CDN 进行分发,可对直播系统的转码、急速高清等能力进行复用,并录制存储至云点播。TRTC 包含两大基础场景:第一个场景是 多人实时互动,针对多人实时互动深度优化,实现全球端到端延迟小于 300 毫秒,抗丢包率超过 80%,抗网络抖动超过 1000 毫秒。单个房间可支持 300 人同时在线,50 人同时上行音视频。第二个场景是 超低延时直播,观众可实现平滑上下卖,单房间 10w 人一秒以内低延迟播放。TRTC 技术特性在实时互动的场景下,用户的音频数据是“既发又收”的,需要经过 3A 处理。比如某音频经过云端的传输后,再通过外放播放该音频,很难避免的会产生回声,而且在通话过程中也会有各种背景噪音等不良体验。我们在讲话过程中声音是连续的,当把时间颗粒度放小会发现声音其实就是连续的波形,如果在传输时丢了一部分,那么就可以根据这个波形来补齐,这就是 PLC 技术。但如果丢的内容过多,就很难再恢复了。而 TRTC 技术则可以很好的应对音频连续丢包的场景,它会根据历史语言帧进行上下文的分析,最后波形合成,通话效果会很顺畅。此外,TRTC 由全链路 H.265 支持,相比 H.264,在相同画质下它会有大约 30 的带宽节省。二、TRTC 入门 - 快速跑通 Demo(音视频互动)那么 TRTC 到底应该如何开发使用呢,在这里我基于 Web 场景下的 vue 2.0 进行实操演示。• 创建应用首先进入腾讯云音视频主页,注册登录后首页如下;然后选择“开发辅助”下的“快速跑通 Remo”,设置应用名称后点击“创建”;• 下载源码接下来就可以开始源码的下载了,云平台为我们提供了各个平台的源码,可以在 Github 和 Gitee 进行云端下载或者直接下载压缩包至本地;在这里我选择 Web 的 zip 包进行下载,下载后解压,是一个名为“Web”的文件夹;• 基于 vue2.0 运行源码接下来使用开发工具打开我们需要的 quick-demo-vue2-js 文件(我用的是 WebStorm);打开控制台 Terminal,首先输入 npm i 下载 vue 项目所需要的包;接下来就可以启动项目了,在控制台输入 npm run serve 进行启动,运行成功后出现运行地址,点击地址即可运行;运行效果如下;• 获取 SDKAppID 和密钥正常运行后,回到腾讯云音视频平台,选择“已下载,下一步”;可以看到这里已为我们生成 SDKAppID 和密钥;复制然后将其输入到已运行页面中指定的位置即可;• 开始视频通话输入密钥以及 SDKAppID,就可以进行相关的音视频操作了,用户 id 和房间 id 已经默认配置;点击“进入房间”,运行成功效果如下;除此之外还可以进行共享屏幕、邀请好友加入视频等操作等操作,我们的每一步操作都会打印日志显示到左侧日志栏(log)中;至此,音视频互动 Demo 运行成功。三、TRTC 进阶 - 集成即时通信 IM 服务即时通信 IM(Instant Messaging) 是一个简单接入、稳定必达、覆盖全球的即时通信云服务。通过植入 SDK 就可集成聊天、会话、群组、资料管理能力,实现文字、图片、短语音、短视频等富媒体消息收发,全面满足通信需要。快速集成即时通信 IM 服务Web 环境下的 IM 集成开发环境要求如下:Vue 3 TypeScript sass(sass-loader 版本 ≤ 10.1.1) node(12.13.0 ≤ node 版本 ≤ 17.0.0) npm(与 node 版本匹配)• 创建项目首先使用 vue-cli 来创建项目,在本地创建一个文件夹作为我们的项目文件夹;如果本地没有 vue-cli,在 cmd 通过命令 npm install -g @vue/cli@4.5.0 sass sass-loader@10.1.1 下载;在文件夹中点击右键,选择“在终端中打开”;终端窗口中输入命令 vue create chat-example 后回车,按照如下提示进行选择;上下键切换,空格选中,回车确认。项目创建成功;• 下载并使用 TUIKit 组件库TUIKit 是基于腾讯云 IM SDK 的 UI 组件库,提供了一些通用的 UI 组件,包含会话、聊天、关系链、群组、音视频通话等功能。首先 cd chat-example 切换到项目所在目录,使用如下命令下载 TuIKit 组件;npm i @tencentcloud/chat-uikit-vue xcopy .\node_modules\@tencentcloud\chat-uikit-vue .\src\TUIKit /i /e下载完成后项目中会出现 TUIKit 目录:接下来 main.js 文件中引入 TUIKit 组件;import { createApp } from 'vue'; import App from './App.vue'; import { TUIComponents, TUICore, genTestUserSig } from './TUIKit'; const SDKAppID = 0; // Your SDKAppID const secretKey = ''; //Your secretKey const userID = ''; // User ID // init TUIKit const TUIKit = TUICore.init({ SDKAppID, }); // TUIKit add TUIComponents TUIKit.use(TUIComponents); // login TUIKit TUIKit.login({ userID: userID, userSig: genTestUserSig({ SDKAppID, secretKey, userID, }).userSig, // The password with which the user logs in to IM. It is the ciphertext generated by encrypting information such as userID.For the detailed generation method, see Generating UserSig }); createApp(App).use(TUIKit).mount('#app');• 获取 SDKAppID 、密钥、userID此步骤与第一节 Demo 案例的操作是相同的,进入 即时通信 IM 控制台进行登录,然后创建一个新应用;在应用配置界面中可获得我们需要的 SDKAppID 、密钥、userID;user ID 可通过在“账号管理”中新建账号获得;最后将获取到的 SDKAppID 、密钥、userID 填入 main.js 中即可;• 调用 TUIKit 组件相关数据配置完成之后,就可以调用我们的 TUIKit 组件了。在需要使用组件的页面调用即可,例如我在 App.vue 页面中调用:<template> <div class="home-TUIKit-main"> <div :class="env?.isH5 ? 'conversation-h5' : 'conversation'" v-show="!env?.isH5 || currentModel === 'conversation'"> <TUISearch class="search" /> <TUIConversation @current="handleCurrentConversation" /> </div> <div class="chat" v-show="!env?.isH5 || currentModel === 'message'"> <TUIChat> <h1 style="margin-top: 20px;text-align: center">腾讯云即时通信IM</h1> <h3 style="color: #149985; margin-top: 10px;text-align: center">体验官 —— 敬 之(马金建)</h3> </TUIChat> </div> </div> </template> <script lang="ts"> import { defineComponent, reactive, toRefs } from 'vue'; import { TUIEnv } from './TUIKit/TUIPlugin'; export default defineComponent({ name: 'App', setup() { const data = reactive({ env: TUIEnv(), currentModel: 'conversation', }); const handleCurrentConversation = (value: string) => { data.currentModel = value ? 'message' : 'conversation'; }; return { ...toRefs(data), handleCurrentConversation, }; }, }); </script> <style scoped> .home-TUIKit-main { display: flex; height: 100vh; overflow: hidden; } .search { padding: 12px; } .conversation { min-width: 285px; flex: 0 0 24%; border-right: 1px solid #f4f5f9; } .conversation-h5 { flex: 1; border-right: 1px solid #f4f5f9; } .chat { flex: 1; height: 100%; position: relative; border: 2px solid #999; } </style>• 启动项目打开控制台,输入命令 npm run serve 启动项目;启动成功效果:接下来就可以体验聊天功能了。点击“发起单聊”,输入我们上面获得的 userID 并按下回车进行搜索,选择联系人后开始单聊。如下为聊天页面;除此之外还有群聊功能,可选多个用户,设置群头像、ID、群类型等。四、TRTC 产品使用体验此次体验,我主要进行了两个方面的开发实践:Ⅰ云平台音视频 Demo 的快速跑通快速跑通 Demo 这一模块整体上的步骤设计简洁高效,只需 3 步:创建应用 --> 下载源码 --> 获取 SDKAppID 和密钥,然后就可以运行项目了。不得不说,这一开发辅助模块的存在意义重大。对于大多数开发者来说,谈起云平台和云服务,可能都会觉得这些东西很“高大尚”,自己没用过也不知道怎么用等想法,原因当然不是因为他们的水平不够高,而是对云平台和云服务的缺乏足够的认知,特别是缺乏实践,作为一种引领产业发展的服务,部分开发者可能都会觉得操作起来很难,导致不愿意去上手。而开发辅助这一模块的设计基本上消除了上面的顾虑,只要上手使用后就会发展它的操作是真简单,步骤非常明确,且几乎是全平台覆盖,无论我们是哪一类开发者,均可上手。在可以跑通 Demo 之后,对于云平台的操作其实可以说就没有什么问题了,因为其他的 SDK 和服务的使用方法也基本上是相同的。个人的建议想法是可以针对开发辅助这一部分可以重点推荐,引导开发者去上手,因为只有在操作过后才会进一步的深入认识这些云服务,才能够体验到它们优势所在。虽然内容基础,但是至关重要。Ⅱ 即时通信 IM 云服务的搭建与使用第二部分我对即时通信 IM 云服务进行了使用,实现了在线单聊与群聊。说实话这是我第一次了解 IM,才发现原来聊天功能的实现“就靠它”。我使用的是 Web & H5,需要用到 TUIKit 组件,但是不知道为什么开发环境只支持 Vue3 和 TypeScript,所以我不得不重新创建项目进行演示(上文有详细步骤),官方文档也有着对 IM、TUIKit 和操作方法的详细介绍。最后在项目中调用成功的页面是这样的;相信对于没有使用过云服务的开发者来说,想要实现这个功能应该很难很难吧,但是在这里就是这么简单,我们需要做的就是调用,其他的云平台都已经为我们做好了。大体上云平台的操作无区别,简单高效;项目的操作也有详细介绍,个人建议想法是 web & h5 是否可以集成 vue2 和 JavaScript?其次云服务文档可以做的更加显眼一点,或者直接标明“IM 服务 开发文档”等,一目了然直接进入,目前是在这个位置:写在最后对于我这样一个前端开发者来说,在使用腾讯云 TRTC 之后的最大体会就是高效,仅需 2 行代码即可跑通测试 Demo,10 行代码完成通用能力的接入,就是简单的创建 --> 下载 --> 引用,我们仅需要获得它的 SDKAppID 、密钥即可享受到各种高品质的音视频服务。其次是它的通用性,几乎是全平台互通,提供覆盖全平台的 SDK 且兼容各大开发框架,真所谓可帮助全球开发者快速搭建低成本、低延迟、高品质的音视频互动解决方案。
0
0
0
浏览量1117
锅从天上来

【云原生 • Kubernetes】kubernetes 核心技术 - RC、Replica Set

1. Repliaction Controller 概述Replication Controller(RC) 是 Kubernetes 系统中核心概念之一,当我们定义了一个 RC 并提交到 K8s 集群中以后,Master 节点上的 Controller Manager 组件就得到通知,定期检查系统中存活的 Pod,并确保目标 Pod 实例的数量刚好等于 RC 的预期值,如果有过多或过少的 Pod 运行,系统就会停掉或创建一些 Pod。此外我们也可以通过修改 RC 的副本数量,来实现 Pod 的动态缩放功能。由于 Replication Controller 与 Kubernetes 代码中的模块 Replication Controller 同名,所以在 K8s v1.2 版本时,它升级为了一个新的概念 Replica Sets,官方解释为下一代的 RC。二者主要的区别在于:Replica Sets 支持基于集合的 Label selector。RC 只支持基于等式的 Label Selector。所以 Replica Set 是很少单独使用的,它主要被 Deployment 这个更高层面的资源对象所使用,从而形成一整套 Pod 创建、删除、更新的编排机制。RC 常用操作配置文件apiVersion: v1 kind: ReplicationController metadata: name: tomcat-rc spec: replicas: 3 template: metadata: name: Tomcat-ReplicationController labels: app: App component: neo4j spec: containers: - name: tomcat image: tomcat: 8.0 ports: - containerPort: 8080Kind: ReplicationController 中的值 ReplicationController 表示 kubectl 将使用 yaml 文件来创建 Replication Controller(RC)。name: tomcat-rc 将用于识别创建 Replication Controller(RC) 的名称。name: tomcat 表示容器的名称定义为 tomcat,pod 中出现的容器是 tomcat。replicas: 3 表示需要在 pod 生命周期的任何时间点维护一个 pod 的三个副本。containerPort: 8080 是确保集群中的所有节点都暴露在同一个端口 8080 上。缩容 Podkubectl scale replicationcontroller tomcat-rc --replicas=1 replicationcontroller "tomcat-rc" scaled kubectl get pod -l name kubectl get rc tomcat-rc扩容 Podkubectl scale replicationcontroller tomcat-rc --replicas=4 replicationcontroller "tomcat-rc" scaled kubectl get pod -l name kubectl get rc tomcat-rc判断及修改副本数量判断当前副本数是否为3个,如果是,则更改为1个副本:kubectl scale rc tomcat-rc --current-replicas=3 --replicas=12. Replica Set 概述Replica Set 跟 Replication Controller 没有本质的不同,只是名字不一样,并且 ReplicaSet 支持集合式的 selector。Kubernetes 官方强烈建议避兔直接使用 ReplicaSet,而应该通过 Deployment 来创建 RS 和 Pod。由于 Replica Set 是 Replication Controller 的代替物,因此用法基本相同。3. Deployment 概述Deployment 是 Kubenetes v1.2 引入的新概念,Deployment 目的主要是为了更好的解决 Pod 的编排问题,Deployment 内部使用了 Replica Set 来实现。Deployment 的定义与 Replica Set 的定义类似,除了 API 声明与 Kind 类型有所区别。如下为 Deployment 定义方式:apiVersion: extentsions/v1beta1 kind: Deployment metadata: name: frontend spec: replicas: 1 selector: matchLabels: tier: frontend matchExpressions: - {key: tier, operator: In, values: [frontend]} template: metadata: labels: app: app-demo tier: frontend spec: containers: - name: tomcat-demo image: tomcat ports: - containerPort: 8080可以看到,该定义方式与 Replica Set 区别除了 apiVersion 和 kind 两个参数不同之外,其他都是一样的。
0
0
0
浏览量2008
锅从天上来

【云原生 • Kubernetes】k8s功能特性、k8s集群架构介绍 敬 之 已于 2022-

一、Kubernetes 的特性/功能自动装箱:基于容器对应用运行环境的资源配置,要求自动部署应用容器,无需太多人工干预。自我修复:也就是自愈能力,容器启动失败时自动重启容器;当部署的 Node 节点出现问题时,会对容器进行重新部署和调度;当容器未通过监控检查时,会关闭此容器,直到容器正常运行才会对外提供服务。水平拓展:伸缩性强,通过简单的命令、用户 UI 界面或 CPU 等资源使用情况,对应用容器进行规模扩大或缩减。服务发现:也就是负载均衡,用户无需使用额外的服务发现机制,就可以基于 k8s 自身能力实现服务发现和负载均衡。滚动更新:可以通过应用的变化,对容器中运行的应用进行一次性或批量更新。版本回退:可根据应用部署情况,对容器中运行的应用进行历史版本即时回退。密钥和配置管理:在无需重新构建镜像的情况下,可部署和更新密钥和应用配置,类似于热部署。存储编排:自动实现存储系统挂载及应用,对有状态的应用实现数据持久化,存储系统可以来自于本地目录、网络存储(NFS、ceph、Gluster 等)。批处理:可提供一次性任务、定时任务,满足批量数据处理和分析。以上 k8s 特性,如果仅使用 docker 容器技术是很难实现或者根本无法实现的。k8s 的目的就是让部署容器化应用更加简洁、更加高效。二、Kubernetes 集群架构介绍搭建一个 k8s 集群,需要包含 master-node 和 worker-node 两大部分。master-node:主控节点,专门管理各个工作节点。 worker-node:工作节点,做具体操作事务的节点。以下将具体介绍各部分中所包含的具体组件,后续在实操搭建 k8s 集群的过程中这些组件都需要我们手动安装。1. master node 节点API server:集群的一个对外统一入口,可以将它理解为 master 节点中各个组件的协调者,通过 apiserver 可将获取到的请求分发至各组件;需要知道,apiserver 是以 restful 请求方式提供服务的,所有请求也就是以 restful 风格通过 apiserver 进入集群后进行相关操作,最后 apiserver 将所有操作数据存储于 etcd当中。etcd:分布式,可靠的键值存储,可用于分布式系统中存储关键核心数据。从简单的应用程序到 Kubernetes 再到任何复杂性的应用程序都可以从 etcd 中读写数据。此处专用于保存集群相关的数据。scheduler:致力于节点调度,它会选择某一个 node 节点进行应用的部署。controller-manager:顾名思义它主要做的就是集中的处理控制管理,集群中后台的一个统一控制组件。处理集群中常规后台任务,一个资源对应一个控制器(controller)。2. worker node 节点kubelet:可以理解为 master 派到 node 节点的一个“代表”,管理当前节点中容器的各种操作。kube-proxy:提供网络代理,实现负载均衡等操作。docker:参见往期文章,此处不再赘述。三、Kubernetes 核心概念在操作 kubernetes 的过程中,难免会遇到一些概念性的问题,以下可以说是 kubernetes 中最重要的三个核心即Pod、Controller、Service。1. Podkubernetes 中最小的部署单元;是一组容器的集合,每一个 pod 中的容器都是共享网络的;pod 的生命周期是短暂的,并非一直存在,会随着服务器的重新启动或者重新部署而更新。2. Controller可以确保预期的 pod 副本数量;当我们在 k8s 中部署容器或应用时,可以无状态部署或有状态部署;可以确保所有 node 都运行同一个 pod;可以支持一次性任务和定时任务。无状态:容器或应用内无任何约定,即使迁移之后也可以直接使用。 有状态:容器或应用内包含约定,如该容器/应用网络 IP 需要唯一等。3. Service定义一组 pod 的访问规则。总体流程就是,通过 service 统一入口访问,由 controller 创建 pod 进行部署。
0
0
0
浏览量223
锅从天上来

【云原生 • DevOps】influxDB、cAdvisor、Grafana 工具使用详解

一、时序数据库 influxDB1. 什么是 influxDBinfluxDB 是一个分布式时间序列数据库,运维常用。由于 cAdvisor 仅仅显示实时信息,但是不能存储监视数据。因此我们需要提供时序数据库用于存储 cAdvisor 组件所提供的监控信息,以便显示除实时信息之外的时序数据。实时信息之外的时序数据:比如当前的内存大小、CPU 的占用情况等。2. influxDB 的安装第一步:下载镜像;docker pull tutum/influxdb第二步:创建容器;docker run -di \ -p 8083:8083 \ -p 8086:8086 \ --expose 8090 \ --expose 8099 \ --name influxsrv \ tutum/influxdb该容器中为 Web 访问端口,8086 端口为数据写入端口,8090 :8083 端口和 8099 是要求暴露出来的端口。第三步:容器创建成功之后,在本地进行访问,显示如下界面即安装完成;3. influxDB 常用操作创建数据库我们可以通过查询模板 “Query Templates” 快速输入相关命令;输入命令后按下回车,即可创建成功;创建用户并授权--创建用户 majinjian,密码 990214,为该用户赋予所有权限 CREATE USER "majinjian" WITH PASSWORD '990214' WITH ALL PRIVILEGES此时搜索用户,可以看到我们创建的新用户;用户授权语法如下:on 数据库名 to 用户名;--在 majinjian 数据库中为用户 majinjian 授予所有权限 grant all privileges on majinjian to majinjian --在 majinjian 数据库中为用户 majinjian 授予写权限 grant WRITE on majinjian to majinjian --在 majinjian 数据库中为用户 majinjian 授予读权限 grant READ on majinjian to majinjian 查看采集的数据查看采集数据需要使用指令 SHOW MEASUREMENTS;可以看到此时是没有内容的,因为我们的数据库刚刚创建,并没有产生数据。二、容器监控工具 cAdvisor1. 什么是 cAdvisorcAdvisor 是 Google 开源的用于监控基础设施应用的工具,是一个强大的监控工具,不需要任何配置就可以通过运行在 Docker 主机上的容器来监控 Docker 容器,而且可以监控 Docker 主机。该应用的主要作用就是监控,而监控所产生的数据均存储于时序数据库 influxDB 中。2. cAdvisor 的安装第一步:下载镜像;docker pull google/cadvisor第二步:创建容器并连接 influxDB;docker run --volume=/:/rootfs:ro --volume=/var/run:/var/run:rw --volume=/sys:/sys:ro --volume=/var/lib/docker/:/var/lib/docker:ro --publish=8080:8080 --detach=true --link influxsrv:influxsrv --name=cadvisor google/cadvisor -storage_driver=influxdb -storage_driver_db=majinjian -storage_driver_host=influxsrv:8086 -storage_driver_db=majinjian -storage_driver_host=influxsrv:8086 语法为连接 influxDB 数据库,此处的 majinjian 是我在 influxDB 中创建的数据库名。 第三步:在本地使用 虚拟机/服务器 IP:8080/containers/ 进行访问,看到以下界面即 cAdvisor 安装成功;此时 cAdvisor 就已经处于运行状态了,它也会将监控产生的数据存入 influxDB 当中。再次查看 influxDB 中的采集数据,可以看到已有数据产生;三、图表工具 Granfana1. 什么是 Grafana通过上一节可以看到,在 influxDB 中查看数据时,数据比较凌乱且不够直观,而 Grafana 正是来解决这个问题的。Grafana 是一个可视化面板,有着非常好的图表和布局展示,包含功能齐全的度量仪表盘和图形编辑器。支持 Graphite、zabbix、influxDB 和 OpenTSDB 作为数据源。它的主要特性为:灵活丰富的图形化选项;可以混合多种风格;支持白天和夜间模式的切换;支持多个数据源。2. Grafana 的安装第一步:下载镜像;docker pull grafana/grafana第二步:创建容器并连接 influxDB;docker run -d -p 3001:3000 -e INFLUXDB_HOST=influxsrv -e INFLUXDB_PORT=8086 -e INFLUXDB_NAME=majinjian -e INFLUXDB_USER=majinjian -e INFLUXDB_PASS=majinjian --link influxsrv:influxsrv --name grafana grafana/grafana -e INFLUXDB_NAME=majinjian 数据库名称 -e INFLUXDB_USER=majinjian 数据库用户名 -e INFLUXDB_PASS=majinjian 数据库密码第三步:本地浏览器进行访问,初始界面如下;输入用户名和密码登录,默认用户名为 admin,密码为 admin,首次登录后需要修改密码;3. Grafana 的常用操作添加数据源点击设置 --> “Data sources”;点击 “Add date source” 添加数据源,然后我们这里选择 influxDB;设置相关参数;点击 “save & test”,如下添加成功;添加仪表盘选择 “Dashboards” --> “Browse”;点击 “New Dashboards” 添加,然后选择一种图表类型添加;接下来就进入了图表编辑页面,可以设置数据源、图表标题、X轴、Y轴等各种属性;如下是我按照容器名称索取的数据;设置完成之后,点击 “save” 进行保存,如下为添加成功后图表;当微服务开始运行后产生的数据便会体现在此图表上。
0
0
0
浏览量388
锅从天上来

【云服务器 ECS 实战】一文掌握弹性伸缩服务原理及配置方法

1. 弹性伸缩概述弹性伸缩(Auto Scaling)就是自动为我们调整弹性计算资源大小,以满足业务需求的变化,是一种根据业务需求和策略自动调整计算能力的服务。简单可以理解为它会根据服务器使用情况,自动的增减服务器的实例数量。在阿里云服务器 ECS 中弹性伸缩是这样实现的。比如在一个负载均衡中挂载了三台 ECS 服务,当因为用户访问量大等状况导致云服务资源不够用的时候,云监控会自动感知(可通过 CPU 的使用率等指标判断),并触发事件来通知弹性伸缩服务根据配置规则来自动添加资源,反之也是如此。通过这样的原理以实现资源的自动化扩容与收缩。自动化的资源调配 就是弹性伸缩的最大优势。此外,弹性伸缩还可以实现资源的自动故障替换。当云监控发现其中一台 ECS 服务器发生故障或者不可用时,就会从资源池中拿一台 ECS 过来进行替换。在应用弹性伸缩服务的时候,我们应避免以下几点错误认知:弹性扩容一定能解决我们整体的性能瓶颈;需找到问题根本所在进而针对性解决才行。弹性伸缩免费;弹性伸缩服务是免费的,但通过弹性伸缩自动创建或者手工加入的 ECS 实例需按照相关实例类型进行付费。2. 实现模式弹性伸缩服务的实现模式有以下几种:3. 基于 GRE 实现 VPC 的互联GRE(Generic Routing Encapsulation,通用路由封装)协议,是指把两个不同的 VPC 网络通过建立一条虚拟隧道的方式连接到一起。假设在两个不同的地域各有一个 VPC 网络,每个 VPC 中均包含三个 ECS 实例(主机),其中一个实例具有公网 IP。当我们想要让这两个 VPC 网络中的某 ECS 实例可以互相访问,就需要设置 GRE 通道,将具有公网 IP 的主机作为跳板建立隧道来实现连接。可以看到,想要通过 GRE 来实现互联的 VPC 网络中必须有一台主机是具备公网 IP 的。4. 弹性伸缩服务的配置使用4.1 创建伸缩组回到阿里云服务器控制台,点击左侧菜单栏的“弹性伸缩”进入弹性伸缩控制台;弹性伸缩的快速配置分为三部,“创建伸缩组” --> “创建伸缩规则” --> “完成并启用”;伸缩组的创建不必多说,当我们选择实例来源是已有实例时,该实例本身不会自动加入到伸缩组内,伸缩组仅提取该实例使用的基础镜像,不会包含该实例的数据信息;在高级配置中,可为该伸缩组添加扩缩容策略、关联负载均衡和数据库等;伸缩规则即在该伸缩组中定义哪些操作被允许。在“执行的操作”选项中,有 调整至、增加、减少 三个选择。增加就是扩容 ECS 后台服务;减少就是移除;调整至即指定调整到多少台;冷却时间指的是该规则被使用之后多长时间内不能再次被使用;选择相关属性后点击“完成”,伸缩组就创建成功了。我们上一步选择的是“稍后手动执行”,所以它处于停用状态,需手动开启;新创建的伸缩组由于还未进行任何配置,所以各项指标均为 0;接下来进行弹性伸缩的相关配置。4.2 伸缩配置选择“实例配置来源”下的“创建伸缩配置”,进入弹性伸缩管理控制台;在基础配置模块中主要是选择付费模式与实例的规格,镜像选择等,大家根据个人需要自行选择;伸缩配置完成之后就可以选择该规格来自动完成扩缩容操作了,前提需要我们自己来创建伸缩规则。4.3 创建伸缩规则点击已有的伸缩组名称;选择“伸缩规则与伸缩活动”,此时是没有伸缩规则的,点击“创建伸缩规则”;如下:
0
0
0
浏览量2038
锅从天上来

【云原生 • DevOps】一文掌握持续集成工具 Jenkins

一、持续集成工具 Jenkins 介绍1. 什么是持续集成持续集成(Continuous Integration,CI)。随着软件开发复杂度的不断提高,如何更好的协同开发以确保软件开发质量已经成为了开发团队所追求的目标,特别是近年来 “敏捷开发” 在互联网领域的兴起,如何能够在不断变化的需求中快速适应和保证开发质量显得尤为重要。持续集成就是针对这类问题的一种软件开发实践,倡导团队必须经常集成他们的工作,而每次的集成都是通过自动化的构建来验证的,包括自动编译、发布、测试,从而更快发现集成错误,让团队更快的开发内聚的软件。持续集成具有以下特点:是一个自动化的周期性的集成测试过程,从检出代码、编译构建、运行测试,再到结果记录、测试统计等都是自动完成,无需人工干预需要有专门的集成服务器来执行集成构建需要有代码托管工具支持持续集成的出现,保证开发团队交代码的质量,减轻了软件发布时的压力;其次就是全程自动完成,无需太多人工干预,极大的减少了重复的过程,节省了时间、工作量和成本。2. Jenkins 介绍Jenkins 原名 Hudson,2011 年修改为 Jenkins,它是一个开源的实现软件持续集成的工具。官网地址如下(也有中文网址):Jenkins Jenkins – an open source automation server which enables developers around the world to reliably build, test, and deploy their software https://www.jenkins.io/Jenkins 能实时监控集成中存在的错误,提供详细的日志文件和提醒功能,还可以用图表的形式形象的展示项目构建的趋势和稳定性。Jenkins 具有以下特点:易安装:官网下载直接运行易配置:提供了友好的 GUI 配置界面变更支持:能从代码仓库中获取并产生代码更新列表,输出到编译输出信息支持永久链接:用户是通过 Web 来访问 Jenkins 的,而这些 Web 界面的链接地址是永久的,可在任何文档中直接使用集成 E-mail/RSS/IMJUnit/Test NG 测试报告:以图表形式提供测试报告文件指纹信息:会保存哪次集成构建产生了哪些 jars 文件,哪次集成使用了哪个版本的 jars 文件等记录支持第三方插件二、Jenkins 的安装与部署1. 安装 Jenkins第一步,下载 Jenkins 安装包,打开Jenkins 官方文档;点击 “Installing Jenkins”,可以看到可供下载的各个版本;选择 Linux(演示虚拟机为 CentOS 系统)下的 CentOS 系统;可以看到官方提供的在线安装方式;打开 Xhell 并连接虚拟机/服务器,按照以下步骤进行下载;# 下载镜像 wget -O /etc/yum.repos.d/jenkins.repo \ https://pkg.jenkins.io/redhat-stable/jenkins.repo # 安装 rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key # 更新 yum upgrade # 安装 Java 环境 yum install java-11-openjdk #安装 Jenkins yum install jenkins2. 本地访问 JenkinsJenkins 安装完成之后,就可以使用 虚拟机/服务器IP:端口 在本地进行访问了,初始界面如下;根据提示密码存于 /var/lib/jenkins/secrets/initialAdminPassword 目录中;输入密码后进入如下界面;我们选择安装推荐的插件,Jenkins 便会开始自动下载安装,如下正在安装;安装完成后,创建我们的第一个用户;进入 Jenkins 主页如下;3. 插件的安装使用推荐安装方式只能帮我们安装一部分最为常用的插件,有某些插件如 maven 等还是需要我们手动去安装的。点击 “系统管理” --> “插件管理”;在这里可以看到我们需要的插件,按需下载即可;4. 卸载 Jenkins# rpm卸载Jenkins rpm -e jenkins # 检查是否卸载成功 rpm -ql jenkins # 彻底删除残留文件 find / -iname jenkins | xargs -n 1000 rm -rf三、Jenkins 全局配置全局配置的目的在于告诉 Jenkins 各种工具的路径在何处,使得 Jenkins 能够通过插件来调用这些软件。我们这里均采用下载压缩包然后上传虚拟机/服务器的方式进行演示。点击“系统管理” --> “全局配置”,可以看到需要配置的插件,需要配置的有 jdk、git、maven 工具;1. Git 的安装与配置(直接使用 yum 命令安装虽然更为简单但版本会很低,为防止今后报错所以推荐此方式安装) 首先下载 git 压缩包并上传至虚拟机/服务器;按照以下步骤进行操作;#1.解压压缩包 tar -zxvf git-2.27.0.tar.gz #2.在Linux系统中是需要编译源码的,首先下载所需要的依赖 yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel gcc perl-ExtUtils-MakeMaker #3.卸载旧版本的 git(安装依赖是会自动安装 git,所以需要卸载旧版本) yum -y remove git #4.进入解压后的文件夹 cd git-2.27.0 #5.编译git源码 make prefix=/usr/local/git all #6.安装git至/usr/local/git路径 make prefix=/usr/local/git install #7.配置环境变量 vi /etc/profile 在底部加上该行代码:export PATH=$PATH:/usr/local/git/bin #8.配置完成后刷新环境变量 source /etc/profile操作完成之后使用命令 git --version 查看 git 版本,如下 2.27 版本安装成功;[root@192 git-2.27.0]# git --version git version 2.27.0 此时我们查看一下 git 路径 which git; [root@192 git-2.27.0]# which git /usr/local/git/bin/git使用该路径设置全局配置;2. JDK 的安装与配置下载一个 jdk 的 rpm 包并上传至虚拟机/服务器;​然后使用命令 rpm -ivh jdk-8u171-linux-x64.rpm 进行安装;​安装后的根目录为 /usr/java/jdk1.8.0_171-amd64;​使用此路径设置全局;​3. maven 的安装与配置下载 apache-maven .tar.gz 包并上传至虚拟机/服务器;​解压压缩文件;​使用此路径及解压后的文件名设置全局;​全部配置完成之后,点击保存、点击应用。​三、将代码上传至 Git 服务器1. Gogs 的搭建与配置Gogs 是一款极易搭建的自助 Git 服务,它的目标在于打造一个最简单、快速和轻松的方式搭建 Git 服务。使用 Go 语言开发的它能够通过独立的二进制进行分发,支持了 Go 语言支持的所有平台,包括 Linux、Mac OS、Windows 以及 arm 平台。与传统 Git 相比它最大的优势在于拥有图形化界面。第一步:下载镜像 docker pull gogs/gogs;[root@192 ~]# docker pull gogs/gogs Using default tag: latest latest: Pulling from gogs/gogs 97518928ae5f: Pull complete d20a5437c0b4: Pull complete ec9934e62f5f: Pull complete 2a880a4f6876: Pull complete 7bb13647629b: Pull complete 641b202f48eb: Pull complete 8f12f9a5cd7d: Pull complete Digest: sha256:fbae7c126411d3fa3f8fdca17a65b196887ab23e3b7375f682a13daf5806bb19 Status: Downloaded newer image for gogs/gogs:latest docker.io/gogs/gogs:latest [root@192 ~]# 第二步:创建 Gogs 容器 docker run -di --name=gogs -p 10022:22 -p 3000:3000 -v /var/gogsdata:/data gogs/gogs;# 容器名称 gogs # 端口映射,22 端口映射为 10022,3000 端口映射为 3000[root@192 ~]# docker run -di --name=gogs -p 10022:22 -p 3000:3000 -v /var/gogsdata:/data gogs/gogs 3af9726ff2d9430be43f7f3d78c206b9a53d356347e8a92c23316a7d2e6533f8 [root@192 ~]# 第三步:在本地浏览器进行访问,初始界面如下; 此处选择数据库类型为 SQLite3 修改域名为 192.168.200.129 修改应用 URL 为 http://192.168.200.129:3000/​随后点击“立即安装”,Gogs 安装与配置完成;​2. 将本地代码上传至 Gogs 的仓库首先我们创建一个仓库;​创建成功后就可以将代码上传至仓库了;​这里我使用 idea(本地 git 环境已搭建,这里不再赘述)以及一个示例项目演示上传操作;选中项目,右键点击 “file” --> “git” --> “Repository” --> “Reomtes”;​接下来增加远程地址,也就是我们 Gogs 远程仓库的地址;此时就可以进行代码上传了,先点击 “Git” --> “Add”,将项目上传至暂存区;选择 “git” --> “Repository” --> “push” 进行推送;输入用户名和密码登录 Gogs 后即可推送成功;此时再次查看 Gogs 中的仓库,可以看到项目已上传至 Gogs 仓库;代码上传至 Git 演示成功。四、任务的创建与执行登入 Jenkins,点击 “新建 Item”,输入任务名称并选择“构建一个maven项目”;​点击“确定”,之后我们作出如下配置;项目描述源码管理build配置完成,点击保存,项目即创建完成; 返回面板,点击按钮执行此任务;此操作相当于我们将项目文件的执行过程拿到了 Jenkins 系统当中。
0
0
0
浏览量371
锅从天上来

【云原生 • DevOps】devOps 入门、Maven 插件自动部署微服务

一、认识 DevOpsDevOps 介绍在认识 DevOps 之前,我们有必要先了解一下整个软件开发的生命周期,以及开发中会经历哪些过程。软件开发必须包含的两个团队是开发团队、运维团队;开发团队将开发计划从头开始设计并完成整体系统的构建(系统迭代更新) 运维团队将开发团队的代码进行测试后部署上线(维持系统稳定运行)由目标不同的两个团队协同完成一个软件的开发,一般来说他们是这样进行协同的:开发团队制定好计划并完成代码编写后提供给运维团队,然后运维团队向开发团队反馈需要修改的 BUG 以及需要返工的任务。在这个过程中,开发人员需要经常性的等待运维人员的反馈,这就导致事件的延长并推迟了软件开发周期。现在互联网模式推崇敏捷开发,项目的迭代速度更快,由于开发与运维人员的沟通问题就导致敏捷开发基本不可能实现。为解决以上问题 DevOps 应运而生,它的全称为【Development&Operations-开发&运维】。正如 DevOps 的标志(无穷大 ∞)一样,它是一个不断提高效率且持续不断工作的过程。DevOps 管理软件生命周期DevOps 的核心在于简化 Dev 和 Ops 两个团队之间的工作流程,使软件的整体开发过程更加快捷。软件的整体开发流程包括:PLAN:开发团队根据用户的目标制定开发计划 CODE:根据 PLAN 开始编码过程,将不同的代码存储在一个库中 BUILD:编码完成后,将代码构建并且运行 TEST:构建项目后,测试代码是否存在 BUG 或错误 DEPLOY:代码经过手动测试和自动化测试后,认定代码已经准备好部署并交给运维团队 OPERATE:运维团队将代码部署到生产环境中 MONITOR:项目部署上线后持续监控产品 INTEGRATE:将监控阶段收到的反馈发送回 PLAN 阶段,整体反复,持续集成、持续部署最终可以总结出 DevOps 的定义:高效组织团队之间如何通过自动化的工具协作和沟通来完成软件的生命周期管理,从而更快、更频繁的交付更稳定的软件。二、Maven 插件使用详解微服务的部署有两种方法:手动部署,先基于源码打包成 jar 包或 war 包,然后将 jar 包或 war 包上传至虚拟机并拷贝至 JDK 容器。通过 Maven 插件自动部署,对于数量众多的微服务,手动部署就太过繁琐了,而且非常容易出错,所以 Maven 部署是实际开发中最经常使用的部署方法。使用 Maven 插件自动部署微服务第一步:修改宿主机的 Docker 配置,让它可以远程访问(Docker 远程操作默认是关闭的);[root@192 ~]# vi /lib/systemd/system/docker.service进入文件后,在 ExecStart= 后面添加以下配置;-H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock第二步:刷新配置,重启服务,依次执行以下代码;[root@192 ~]# systemctl daemon-reload [root@192 ~]# systemctl restart docker [root@192 ~]# docker start registry registry 第三步:打开我们需要进行自动部署的项目,在 pom.xml 文件中增加以下配置; <build> <finalName>app</finalName> <plugins> <!--第一个插件:spring-boot的maven插件--> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <!-- 第二个插件:docker的maven插件,官网:https://github.com/spotify/docker-maven-plugin --> <plugin> <!--插件的类以及版本号--> <groupId>com.spotify</groupId> <artifactId>docker-maven-plugin</artifactId> <version>0.4.13</version> <!--配置部分--> <configuration> <!--最后生成的镜像名称--> <imageName>192.168.200.129:5000/${project.artifactId}:${project.version}</imageName> <!--基础镜像--> <baseImage>jdk1.8</baseImage> <!--入口点--> <entryPoint>["java", "-jar", "/${project.build.finalName}.jar"]</entryPoint> <resources> <!--指定的源--> <resource> <targetPath>/</targetPath> <directory>${project.build.directory}</directory> <include>${project.build.finalName}.jar</include> </resource> </resources> <!--宿主机/服务器地址--> <dockerHost>http://192.168.200.129:2375</dockerHost> </configuration> </plugin> </plugins> </build>(以下我将以一个个人项目作为示例进行操作,我使用的软件是 idea;)第四步:使用 Maven 命令调用插件,先打开命令行窗口;输入 mvn install,此命令会将当前目录下工程以及所有子工程安装至本地仓库;第五步:为某个工程创建 Docker 镜像(这里的示例项目只有一个工程,所以我直接在根目录进行操作,如果目录下有多个子工程,可先进入子工程:输入 cd 然后直接将目录拖到命令行窗口即可);输入 mvn docker:build -DpushImage,此命令为创建并上传 docker 镜像;在此处可能会出现无法连接服务的问题,报错如下;检查 idea 的 Docker 配置是否连接了宿主机的 2375 端口,点击 “file” --> “setting” --> docker,查看 TCP socket;如下为创建并上传成功;此时查看宿主机镜像,可以看到我们刚刚创建的快照版镜像;同时访问 192.168.200.129:5000/v2/_catalog 查看我们的私有仓库是否有此镜像;通过 Docker-Maven 插件实现微服务部署演示完成。
0
0
0
浏览量2010
锅从天上来

【云原生 • Docker】docker 私有仓库的搭建、配置与镜像上传

一、私有仓库的搭建与配置所谓的 Docker 私有仓库,就是指企业内部所使用的仓库。仓库用于存放各种镜像,区别在于公有仓库所存储的都是一些通用型的镜像比如N Tomcat 镜像、ginx 镜像等。私有仓库则用于存放自身开发的企业级应用。如果想要在一个局域网来共享一些镜像,那么就需要用到私有仓库。1. 拉取私有仓库镜像 docker pull registry;[root@192 ~]# docker pull registry Using default tag: latest latest: Pulling from library/registry 79e9f2f55bf5: Pull complete 0d96da54f60b: Pull complete 5b27040df4a2: Pull complete e2ead8259a04: Pull complete 3790aef225b9: Pull complete Digest: sha256:169211e20e2f2d5d115674681eb79d21a217b296b43374b8e39f97fcf866b375 Status: Downloaded newer image for registry:latest docker.io/library/registry:latest [root@192 ~]# 2. 创建私有仓库,占用 5000 端口;[root@192 ~]# docker run -di --name=registry -p 5000:5000 registry此时已经算是完成了私有仓库的构建,如下;3. 测试连接,在本地浏览器中输入 192.168.200.129:5000/v2/_catalog 进行访问,可以成功访问则说明私有仓库搭建完成。成功效果如下:192.168.200.129 是我的 Docker 宿主机(虚拟机)IP 地址,大家操作时注意查看自己的的宿主机 IP。4. 修改 /etc/docker/daemon.json 文件,此步骤的目的是让 Docker 能够信任该私有仓库的地址,只有这样之后才能将本地镜像上传至私有仓库;[root@192 ~]# vi /etc/docker/daemon.json在该文件中加入以下代码:"insecure-registries":["192.168.200.129:5000"]修改配置文件之后,重启 Docker 使其生效;[root@192 ~]# systemctl restart docker二、镜像上传至私有仓库此处我以 jdk1.8 镜像为例进行操作演示。1. 标记要上传的镜像为私有仓库镜像;[root@192 ~]# docker tag jdk1.8 192.168.200.129:5000/jdk1.8此时再次查看 Docker 中的镜像,可以看到 jdk1.8 镜像已经被标记;2. 启动 registry 容器;[root@192 ~]# docker start registryregistry3. 上传被标记的镜像至私有仓库;[root@192 ~]# docker push 192.168.200.129:5000/jdk1.8 Using default tag: latest The push refers to repository [192.168.200.129:5000/jdk1.8] e5e377c11436: Pushed 6e64d4a7ac94: Pushed 174f56854903: Pushed latest: digest: sha256:8699db7832cf89668b5812161c55e73454fbc0304d354d06ed0e6ce3ddc493ca size: 949 [root@192 ~]# 4. 测试连接,再次在本地浏览器中输入 192.168.200.129:5000/v2/_catalog 进行访问,可以看到相较于刚创建的私有仓库列表中已添加了 jdk1.8;jdk1.8 上传至私有仓库成功。
0
0
0
浏览量2009
锅从天上来

人尽皆知的云原生,到底是大势所趋还是过度炒作?

传统云平台 VS 云原生要知道,在云原生之前,IT/互联网领域中也是存在着云平台的,即基于虚拟化的传统云平台,典型的有 Openstack 等。在传统方式下,如果说一个企业生产应用,需要部署 100 台应用实例,那么它就得准备 100 个虚拟机,然后再将代码部署上去,最后为应用构建高可用的方案。这样无论生产还是运维耗费精力无疑都是巨大的。了解过云原生的都知道,有一个核心概念容器,而传统云平台与云原生之间必须要关注的少不了容器与虚拟机之间的区别。虚拟机即在宿主机/物理机的基础上装一个操作系统,操作系统之上部署 Hypervisor,由它再带起一个个承担应用的子系统。从这个层面来看它是很复杂的,如果系统出现了某些问题,我们需要去检测宿主机、虚拟机乃至 Hypervisor。而且虚拟机是模拟完整的操作系统,这当然也包括了硬件驱动等等,资源需求很大,一个物理机可以开放的虚拟机是有限的。当我们要部署一个应用时,需要考虑该应用在并发高峰时可能需要需要多少资源,创建虚拟机时按照资源的最大需求进行设定,以防止虚拟机无法支撑应用。但在大部分时间内应用的资源需求并不会一直处于高峰,这就造成了资源利用率很低。除此之外传统云平台其他各方面的缺陷也相当明显,诸如:业务代码与基础架构割裂虚拟机构建和业务代码相互分离基础架构后期维护风险大基础架构无法感知业务状态,升级维护困难缺少自动化需要自己构建应用的高可用方案扩容缩容难故障转移难可见传统的云平台无论对于任何的操作、变更都是非常困难的,需要耗费大量的成本和人力。而云原生正是为解决此问题而生,它鼓励在公有云、私有云、混合云等动态环境中构建和运行规模化应用,可以说云原生是一种思想,是技术和企业管理方法的总结。从技术层面来看:应用程序从设计之初就在为上云而做好了准备云平台基于自动化体系云原生包含的核心技术栈有应用容器化封装、服务网格、不可变基础架构、声明式 API 等。这些技术不仅提升了系统适应性、可管理性、可观察性,使开发者可以以最小成本进行频繁和可预测的系统变更,而且还可以提升部署维护速度和效率,助力业务的快速成长。此外,在使用云原生之后,运维工程师和开发工程师也不会再那么界限清晰,因为大家面向的都是同样的 API。传统下的企业开发、测试、运维都是相互割裂的状态,云原生则将企业开发和运维部门很好地结合起来。所提倡的DevOps理念打破了开发、测试、运维部门之间的隔阂,让整体的应用交付变得更快速。从技术角度看,DevOps 涵盖了应用的开发、编译、构建、测试、打包、发布的自动化流程,并包含了很多 DevOps 工具链。云原生核心项目概览云原生很复杂,它本身是一个很大的生态,包含着几十个甚至上百个项目。这其中最重要的就是 Kubernetes,它主要的作用是集群管理(node)和作业调度(pod),作业调度之后, k8s 通过CSI、CNI、CRI将应用以容器的方式运行起来。那么对外暴露什么样的服务?别人如何访问该服务呢?k8s 本身是通过 kube-proxy 去做东西向的流量的负载均衡和服务发现的, 他还包含了 CoreDNS 也就是集群内的域名服务器以及 Istio等集群服务管理软件。而 k8s 中产生的数据则专存于分布式数据库etcd中。云原生技术演进云原生本身其实是为微服务而服务的,在应用架构上的演进由最开始的单体应用,到分层架构,到 SOA,再到当前流行的微服务。每一个微服务都是一个独立的部署单元,比如说这几个微服务由这个团队负责,那几个微服务由那个团队负责,团队只需关注自己负责的业务即可,不会受全局的影响。微服务也有着启动速度快、资源需求小、部署灵活等诸多优点。此外云原生也不断在朝着应用规模化、计算边缘化、部署多样化、应用复杂化的趋势发展。应用规模化:从概念验证到大规模生产应用计算边缘化:以数据中心为主的云计算到面向边缘节点的边缘计算部署多样化:私有云和公有云混合的多云和混合云应用复杂化:简单的无状态应用到复杂的有状态应用管理还有更重要的局部技术革新,如基于 XDP 和 eBPF 实现的网络加速和应用隔离、基于 WebAssembly 实现的个性化 proxy plugin、不断增强的安全保证手段等等。
0
0
0
浏览量2012
锅从天上来

【云原生 • Kubernetes】集群资源监控概述、监控平台的搭建

一、集群资源监控概述Kubernetes 集群对资源的监控指标主要有集群监控和 Pod 监控两大部分。1. 集群监控即对 k8s 集群本身的监控,主要监控以下内容。节点资源利用率:集群中每个节点的 CPU 资源使用情况、利用率等;节点数:比如说集群共有三个节点,有两个处于忙碌状态,一个节点处于空闲状态,那么在资源分配时就需要节点数进行考虑;集群中运行的pods:每个节点中运行的 pod 数量等。2. Pod 监控Pod 监控,监控集群中运行的 pod 以及容器,主要监控以下内容。容器指标:pod 中运行的容器数量及状态等;应用程序:对容器中运行的应用程序进行监控,可知晓当前集群的运行情况;二、监控平台搭建所需组件概述搭建监控平台需要使用 Prometheus 和 Grafana 两个组件。以下一一介绍:Prometheus(普罗米修斯) 是一套开源组件,可以做到监控、报警功能且集成了时间序列数据库。其基本原理是通过 http 协议周期性抓取被监控组件的状态,这样做的好处是任意组件只要提供 http 接口就可以接入监控系统,不需要任何 sdk 或者其他的复杂集成过程。Grafana 是一个开源的数据分析和可视化工具,有着非常好的图表和布局展示,包含功能齐全的度量仪表盘和图形编辑器。支持 graphite、zabbix、influxDB 和 OpenTSDB 作为数据源。它在此处的作用也就是以可视化的形式展现“普罗米修斯”抓取的状态。Grafana 在往期文章已有详细介绍和操作演示,详情参见 Grafana 工具使用详解组件工作示意图如下:三、搭建监控平台提示:搭建过程中所需文件均已在文末附下载地址,需要自取即可。1. 部署 Prometheus第一步:创建一个目录,用于存放我们需要的 yaml 文件;[root@master ~]# mkdir pg [root@master ~]# cd pg [root@master pg]# 上传 yaml 文件至此目录,我使用的是Xftp 7 工具;上传后如下:第二步:部署守护进程,也就文件中的 node-exporter.yaml 文件;[root@master pg]# kubectl create -f node-exporter.yaml daemonset.apps/node-exporter created The Service "node-exporter" is invalid: spec.ports[0].nodePort: Invalid value: 31672: provided port is already allocated [root@master pg]# 第三步:部署 prometheus 目录下的其他 yaml 文件;[root@master pg]# ls grafana node-exporter.yaml prometheus [root@master pg]# cd prometheus/ [root@master prometheus]# ls configmap.yaml prometheus.deploy.yml prometheus.svc.yml rbac-setup.yaml [root@master prometheus]# kubectl create -f rbac-setup.yaml clusterrole.rbac.authorization.k8s.io/prometheus created serviceaccount/prometheus created clusterrolebinding.rbac.authorization.k8s.io/prometheus created [root@master prometheus]# kubectl create -f configmap.yaml configmap/prometheus-config created [root@master prometheus]# kubectl create -f prometheus.deploy.yml deployment.apps/prometheus created [root@master prometheus]# kubectl create -f prometheus.svc.yml service/prometheus created [root@master prometheus]# 部署完成后,查看 pods,可以看到 prometheus 已存在,部署完成。2. 部署 Grafana部署方式同上,进入 Grafana 目录后,分别执行 yaml 文件;[root@master pg]# ls grafana node-exporter.yaml prometheus [root@master pg]# cd grafana/ [root@master grafana]# ls grafana-deploy.yaml grafana-ing.yaml grafana-svc.yaml [root@master grafana]# kubectl create -f grafana-deploy.yaml deployment.apps/grafana-core created [root@master grafana]# kubectl create -f grafana-svc.yaml service/grafana created [root@master grafana]# kubectl create -f grafana-ing.yaml ingress.extensions/grafana created [root@master grafana]# 部署完成后,查看 pods,可以看到 grafana 已存在,部署完成。3. 打开 Grafana,添加数据源和显示模板首先 kubectl get svc -n kube-system 查看访问 grafana 所需要的端口号;可以看到 grafana 端口号为 30708,接下来在本地浏览器使用 宿主机IP:30708 即可访问 grafana 应用。关于 Grafana 应用的相关操作(添加数据源、添加仪表盘等)往期文章已有详细介绍,参见 Grafana 工具使用详解。
0
0
0
浏览量2011
锅从天上来

【云原生 • Docker】docker 环境搭建、docker 与容器常用指令大全

一、Docker 环境搭建1. 准备工作(已有 Linux 环境可省略)在这里我们用 VM 虚拟机 + CentOS 的环境进行 Docker 部署(建议使用 CentOS 7 以上版本)。首先准备一台 CentOS 系统的虚拟机,可以看到主机的 IP 地址为 192.168.200.129;为了更加直观,我将使用 Xhell 7 连接虚拟机进行操作演示;2. 安装 Docker第一步:yum 包更新到最新;//更新yum sudo yum update第二步:安装需要的软件包,yum-util(提供 yum-config-manager 功能),device-mapper-persistent-data、lvm2(devicemapper 驱动依赖);//安装需要的包 sudo yum install -y yum-utils device-mapper-persistent-data lvm2第三步:设置 yum 源为阿里云;//设置阿里云源 sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo第四步:安装 Docker;//安装docker sudo yum install docker-ce第五步:检查 Docker 版本;//检查 docker 版本 docker -v使用 docker -v 命令可以查看到版本号即说明安装成功。3. 设置 ustc 镜像Docker 安装完成之后还需要执行一个操作那就是设置国内镜像站点,否则 Docker 中下载操作会很慢。ustc 是老牌 Linux 镜像服务提供者,它的 Docker 加速器速度很快,而且不需要注册,是真正的公共服务。需要注意的是在设置之前要先启动 docker 服务,如果不启动服务就编辑 .json 文件是无法正常保存的,因为它无法找到 Docker 进程。启动 Docker 服务使用指令:service docker start然后 vi 进入文件 /etc/docker/daemon.json,在文件中添加以下内容;{ "registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"] }退出保存即可。二、Docker/容器操作命令汇总1. Docker 操作命令systemctl start docker //启动 Docker;systemctl stop docker //停止 Docker;systemctl restart docker //重启 Docker;systemctl status docker //查看 Docker 状态; systemctl enable docker //开机自启动 Docker;docker info //查看 Docker 概要信息;docker --help //查看 Docker 帮助文档;2. 镜像相关命令docker images //查看镜像(这些镜像都存储于 /var/lib/docker 目录下)repository - 镜像名称;tag - 镜像标签;image id - 镜像 id;created - 镜像的创建日期;size - 镜像的大小;docker search 镜像名称 //搜索镜像,从网络查找需要的镜像name - 仓库名称;description - 镜像描述;stars - 用户评价,反映该镜像的受欢迎程度;official - 是否官方;automated - 自动构建,表示该镜像是由 Docker Hub 自动构建流程创建的。docker pull 镜像名称  //拉取镜像,从中央仓库下载镜像到本地如下载 centos 7 镜像:docker rmi 镜像ID //删除镜像,可根据镜像 ID 也可根据镜像名称 docker rmi `docker images -q` //删除所有镜像3. 查看容器docker ps //查看容器 docker ps -a //查看所有容器 docker ps -l //查看最后一次运行的容器 docker ps -f statu=exited //查看停止的容器4. 创建容器docker run docker run 参数包含参数如下:-i  运行容器-t  容器启动后自动进入其命令行--name  为创建的容器命名-v  表示目录映射关系,前者为宿主机目录,后者是映射到宿主机上的目录-d  加了这个参数则会创建一个守护式容器在后台运行(这样创建容器后不会自动登录容器)-p  表示端口映射,前者为宿主机端口,后者是容器内的映射端口常用创建容器的方式为交互式创建容器和守护式创建容器,如下://交互式创建容器 docker run -it --name=容器名称 镜像名称:标签 /bin/bash //退出当前容器 exit//守护式创建容器 docker run -di --name=容器名称 镜像名称:标签 //登录守护式容器 docker exec -it 容器名称/ID /bin/bash5. 停止与启动容器docker stop 容器名称/ID //停止容器 docker start 容器名称/ID //启动容器6. 文件挂载docker cp 需要拷贝的文件/目录 容器名称:目录 //将文件拷贝到容器内 docker cp 容器名称:目录 需要拷贝的文件/目录 //将文件从容器拷贝出来7. 目录挂载在创建容器时,我们可以将宿主机的目录与容器内的目录进行映射,这样就可以通过修改宿主机的目录文件从而直接影响容器了。docker run -di -v 宿主机目录:容器目录 --name=容器名称 镜像名称:标签如果共享多级的目录,可能会出现权限不足的提示。这是由于 CentOS 7 中的安全模块 selinux 将权限禁止了,这时候可以添加参数 --privileged=true 来解决此问题。8. 查看容器 IP 地址docker inspect 容器名称/ID //查看容器 ip 以及相关的各种数据 docker inspect --format='{{.NetworkSettings.IPAddress}}' 容器名称/ID //查看容器 ip 地址并输出9. 删除容器docker rm 容器名称/ID //删除指定的容器需要注意的是如果想要删除一个容器,需要先停止该容器;且如果镜像中有运行状态的容器,也是无法删除容器的。
0
0
0
浏览量2013
锅从天上来

【云原生 • Docker】docker 入门、docker 与虚拟机对比、docker 组件

一、认识 Docker1. 什么是虚拟化虚拟化是一种资源管理技术,将计算机的各种实体资源如服务器、内存、网络等抽象或者转换后呈现出来,打破实体结构间不可切割的状态,使得用户有更好的方式来应用这些资源。虚拟部分不受现有资源的架设方式、地域、物理组态等限制。一般所指的虚拟化资源包括计算能力和存储资源。在实际生产环境中,虚拟化技术主要用来解决高性能的物理硬件产能过剩和老旧硬件产能过低的重组重用,透明化底层物理硬件,达到利用的最大化。虚拟化技术包括软件虚拟化、硬件虚拟化、内存虚拟化、网络虚拟化、桌面虚拟化、服务虚拟化、虚拟机等。2. 什么是 DockerDocker 本身就是一种虚拟化技术,但和传统虚拟化技术又有一定的区别。诞生于 2013 年,是一个开源的项目,它基于 Google 公司的 go 语言实现,后来加入了 Linux 基金会,遵循 apache 2.0 协议,项目在 GitHub 进行维护,它的目标是实现轻量级的操作系统虚拟化解决方案。Docker 的基础是 Linux 容器(LXC),在 LXC 的基础上进行了进一步的封装,让用户无需再去关心容器的管理,使得操作更为简易,用户操作 Docker 的容器就像操作虚拟机一样简单。3. 为什么选择 Docker?上手快;用户仅需几分钟就可以把自己的程序 “Docker” 化,Docker 依赖于 “写时复制(copy-on-write)” 模型,修改程序应 用极为迅速,可以说达到了 “随心所欲,代码即改” 的境界。职责的逻辑分类;使用 Docker,开发人员只需关心容器中运行的应用程序,运维人员只需关心如何管理容器,加强了开发人员的开发 环境与应用程序部署生产环境的一致性。快速高效的开发生命周期;Docker 的目标之一就是缩短代码从开发、测试、部署、上线到运行的周期,让 程序易于可移植性、易于构建和协作。鼓励使用面向服务的架构;Docker 鼓励面向服务的体系架构和微服务架构。它推荐单个容器只运行一个程序或进程,这就形成了分布式的应用 程序模型。Docker 为微服务而生。二、容器与虚拟机的区别首先是传统的虚拟化技术,以 Hypervisor 为例(类似于 VMware 虚拟机)。最底层(第 0 层)为 Server,也就是服务器的硬件;第 1 层为服务器本身的操作系统;第 2 层是管理虚拟机的软件(虚拟层);第 3 层就是虚拟机,可以有若干个,要注意这些虚拟机的操作系统与本地的操作系统是没有任何关系的,因为它是运行在虚拟层的软件上的。其次为容器技术机制,底层和第一层与传统虚拟技术相同。第 2 层为 Docker 引擎,也就是我们安装的 Docker 软件;第 3 层为二进制的一些库和各种应用软件;可以看到,二者的主要区别在于虚拟层和 Docker 引擎(第 2、3 层)。虚拟层可以虚拟一些硬件,虚拟出不同类型的操作系统,所以虚拟操作系统与本地操作类型是不一定一致的。而在 Docker 机制中,每个应用软件(容器)没有自己的操作系统的,它的环境直接依赖于本机操作系统的环境,调用的也直接是本机操作系统。容器是在操作系统层面上实现虚拟化,直接复用本地主机的操作系统,传统方式则是在硬件层面实现。与传统的虚拟机相比,Docker 的优势体现为启动速度快、占用体积小。三、Docker 组件1. Docker 服务器与客户端Docker 是一种客户端-服务器(C/S)架构模式,Docker 客户端只需要向服务器或守护进程发送请求,服务器或守护进程将完成所有工作并返回结果。2. Docker 镜像与容器镜像是构建 Docker 的基石,用户基于镜像运行自己的容器。镜像是基于文件系统的一种层式结构,由一系列指令一步一步构建出来。镜像体积很小,便于分享、存储和更新。Docker 可以帮助构建和部署容器,只需要把自己的应用程序或服务打包放进容器即可。容器是基于镜像启动起来的,容器中可以运行一个或多个进程。可以认为镜像是 Docker 生命周期中的构建或者打包阶段,而容器则是启动或者执行阶段。容器基于镜像启动,一旦容器启动完成后,我们就可以登录到容器中安装自己需要的软件或者服务。所以说容器就是一个镜像格式、一些列标准操作、一个执行环境。3. Registry 注册中心Docker 用 Registry 来保存用户构建的镜像,分为公共和私有两种。Docker 公司运营公共的 Registry 叫做 Docker Hub。用户可以在 Docker Hub 注册账号,分享并保存自己的镜像。Docker Hub 网址如下:Docker Hub https://hub.docker.com/
0
0
0
浏览量2013
锅从天上来

【云原生 • Kubernetes】搭建 k8s 集群(Kubeadm 方式)

一、k8s 集群平台规划k8s 集群可以有两种规划方式,单master集群 和 多master集群。1. 单 master 集群顾名思义该集群中只有一个 master 节点,在这样的集群规划中,如果 master 节点出了任何问题,它所管理的各个 node 节点都会受到影响,缺点是很明显的。2. 多 master 集群(推荐)包含多个 master 节点,在该集群中,master 通过负载均衡对 node 节点进行管理。多 master 集群也称为高可用的 master 集群,即使其中一个 master 节点出现了问题,也不会影响到其他节点。二、集群环境硬件配置要求提示:由于此处是基于虚拟机进行演示操作的,所以以下配置适用于基于虚拟机的测试环境使用,如果是基于服务器的生产环境则该配置需要更高。master 节点:CPU 两核及以上内存 4G 及以上硬盘 20G 及以上node 节点,作为“具体做事”的节点,它的配置要求会更高:CPU 四核及以上内存 8G 及以上硬盘 40G 及以上三、k8s 集群搭建(Kubeadm 方式)Kubeadm 是 k8s 的部署工具,它提供了 kubeadm init 和 kubeadm join,专用于快速部署 k8s 集群,它能通过两条指令完成一个 Kubenetes 集群的搭建。Kubeadm 部署方式的优点是降低了部署门槛,部署方式快捷且简单;但缺点是屏蔽了诸多细节,遇到问题难以排查是哪里出现了问题。注意:下文中的操作步骤,除特别说明在哪个节点操作之外,未说明的均表示该操作在所有节点都得执行。1. 主机准备准备三台虚拟机,分别安装 CentOS 系统。一台作为 master 节点,另两台作为 node 节点,且每台虚拟机有自己的专属 IP 地址。虚拟机的创建和配置注意以下几点:硬件按照上文要求进行配置;虚拟机之间可以进行网络互通;虚拟机可以访问外网,便于下载镜像;安装好 wget 工具 yum install wget;禁止 swap 分区。2. 系统初始化第一步:关闭防火墙#临时关闭 systemctl stop firewalld #永久关闭 systemctl disable firewalld第二步:关闭 selinux#永久关闭 sed -i '/selinux/s/enforcing/disabled/' /etc/selinux/config #临时关闭 setenforce 0第三步:关闭 swap#临时关闭 swapoff -a #永久关闭 sed -ri 's/.*swap.*/#&/' /etc/fstab第四步:设置主机名称,使用命令 hostnamectl set-hostname 主机名,如下三台主机分别设置为:hostnamectl set-hostname master hostnamectl set-hostname node1 hostnamectl set-hostname node2 #查看当前主机名称 hostname第五步:在master节点中添加 hosts,即节点 IP地址+节点名称;cat >> /etc/hosts << EOF 192.168.200.132 master 192.168.200.133 node1 192.168.200.134 node2 EOF第六步:将桥接的 IPv4 流量传递到 iptables 的链(所有节点都设置);#设置 cat > /etc/sysctl.d/k8s.conf << EOF net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 EOF #使其生效 sysctl --system第七步:时间同步,让各个节点(虚拟机)中的时间与本机时间保持一致。yum install ntpdate -y ntpdate time.windows.com3. Docker 的安装Kubernetes 默认容器运行时(CRI)为 Docker,所以需要先在各个节点中安装 Docker。docker 的详细安装步骤往期文章已有讲述,此处不再赘述。详情参见:【云原生 • Docker】docker 环境搭建、docker与容器常用指令大全安装 Docker 后,之后的操作均需在 docker 服务开启的前提下进行 systemctl start docker。4. 添加阿里云 yum 源此步骤是为了便于今后的下载,在每个节点中执行以下配置;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 EOF5. kubeadm、kubelet、kubectl 的安装此处指定版本为 1.18.0,如果不指定默认下载最新版本。#下载软件 yum install -y kubelet-1.18.0 kubeadm-1.18.0 kubectl-1.18.0 #开机自启动 systemctl enable kubelet安装成功如下:6. 在 Master 节点中部署集群在 master 节点中执行以下命令,注意将 master 节点 IP 和 kube 版本号修改为自己主机中所对应的。kubeadm init \ --apiserver-advertise-address=192.168.200.132 \ --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此步骤执行完成之后,使用命令docker images查看系统中的镜像,可以我们需要的镜像均已安装完成。查看提示信息,看到 initialized successfully 说明我们 master 节点上的 k8s 集群已经搭建成功;7. 将 node 节点加入集群查看上一步执行成功后的提示信息,可以看到系统给了我们两条命令;这两条命令分别表示:① 开启 kubectl 工具的使用(该命令在master节点中执行)。mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config② 将 node 节点加入 master 中的集群(该命令在工作节点node中执行)。kubeadm join 192.168.200.132:6443 --token pahgrt.7gn13u88wz4f89an \ --discovery-token-ca-cert-hash sha256:7f73daa421d7564a6f813985a03f860350a923967d05cd955f8223d56200eb5b分别在 master 节点中执行第 ① 条命令,在各个 node 节点中执行第 ② 条命令;执行完成之后在 master 节点中使用命令 kubectl get nodes 查看此时集群中的工作节点。可以看到,node1 和 node2 工作节点已加入至 master 中的集群。8. 部署 CNI 网络插件在上述操作完成后,各个工作节点已经加入了集群,但是它们的状态都是 NoReady,这是由于无它们无法跨主机通信的原因。而 CNI 网络插件的主要功能就是实现 pod 资源能够跨宿主机进行通信。在master节点中执行以下命令进行配置:kubectl apply -f https://docs.projectcalico.org/v3.10/manifests/calico.yaml然后使用命令 kubectl get pods -n kube-system 查看运行状态,1 代表运行中;最后再次使用kubectl get nodes查看集群中的工作节点;可以看到处于开机状态的 master 节点和 node2 节点已经是 ready 状态,处于关闭状态的 node1 节点为 NoReady 状态,测试无误。Kubernetes 集群搭建完成。四、方法总结kubeadm 搭建 k8s 集群简单总结为以下几步:准备虚拟机 3 台,分别安装 CentOS 操作系统,一台作为主控节点 master,两台作为工作节点 node;对安装后的虚拟机进行初始化操作;在所有的节点中安装 docker、kubeadm、kubelet、kubectl;在 master 节点中使用 kubeadm init 命令部署集群;在 node 节点中使用 kubeadm join 命令将 node 节点添加至集群;部署网络插件 CNI。
0
0
0
浏览量2011
锅从天上来

【云原生 • Kubernetes】命令行工具 kubectl 介绍及命令汇总

1. kubectl 概述kubectl 是 Kubernetes 集群的 命令行工具,通过 kubectl 能够对集群本身进行管理,而且能够在集群上进行容器化应用的安装与部署。2. kubectl 命令语法kubectl 命令语法格式如下:kubectl [command] [TYPE] [NAME] [flages]command:指定要对资源执行的操作,如 create、get、describe、delete 等。TYPE:指定资源类型,资源类型的书写对大小写敏感,开发者也可以以单数、复数或者缩略形式书写。NAME:指定资源的名称,名称也对大小写敏感,如果省略名称则会显示所有资源。flages:指定可选的参数,例如可以使用 -s、-server 参数指定 Kubernetes API server 的地址和端口。例如:kubectl get node kubectl get nodes kubectl get nodes node13. kubectl help 获取更多信息使用命令 kubectl --help 可以获取 kubectl 帮助,里面展示了 kubectl 的各种命令以及解释。4. kubectl 命令大全• 基础命令• 部署命令• 集群管理命令• 故障诊断和调试命令• 其他命令
0
0
0
浏览量2010
锅从天上来

【云原生 • Docker】镜像的迁移与备份、Dockerflie 使用方法

一、迁移与备份迁移和备份主要有三个操作命令将容器保存为镜像、备份镜像(将镜像导出为一个文件)、镜像的迁移与恢复。迁移与备份在实际操作 Docker 的过程中使用的是非常多的,比如要将一台服务器的镜像迁移到另外一台服务器,就么可以先将镜像保存为一个文件,然后将文件拷贝至另一台服务器,最后进行镜像的恢复来实现。1. 容器保存为镜像#语法 docker commit 容器名称 镜像名称如下,此时系统中正在运行的容器有 myredis 和 mynginx;[root@192 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 9ddb490f2ac0 redis "docker-entrypoint.s…" 4 hours ago Up 4 hours 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp myredis 90509fb78df4 nginx "/docker-entrypoint.…" 6 hours ago Up 6 hours 0.0.0.0:80->80/tcp, :::80->80/tcp mynginx我们以操作 mynginx 为例,将容器 mynginx 保存为新镜像 mynginx_i;[root@192 ~]# docker commit mynginx mynginx_i sha256:42b5d8d237ebf2ac4dc75dce3f202c3fcf52d7db07383e0649946ad13b5aaa67此时查看镜像,可以看到我们刚刚保存的镜像 mynginx_i;[root@192 ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE mynginx_i latest 42b5d8d237eb 5 minutes ago 141MB nginx latest 605c77e624dd 6 months ago 141MB redis latest 7614ae9453d1 6 months ago 113MB mysql latest 3218b38490ce 6 months ago 516MB centos 7 eeb6ee3f44bd 9 months ago 204MB centos/mysql-57-centos7 latest f83a2938370c 2 years ago 452MB tomcat 7-jre7 47c156f4d4e3 3 years ago 359MB [root@192 ~]# 测试结果,基于此镜像再创建一个 nginx 容器;[root@192 ~]# docker run -di --name=mynginx2 -p 81:80 mynginx_i 846bac2dc9a855590442e551fffe625dc77b41e567864067111956bbfb11e0e8在本地进行访问,如下 nginx 访问成功;可以看到,mynginx_i 镜像已经包含了我们之前部署的静态页面。2. 镜像备份有时候我们需要将本机的一个镜像放到另外一台服务器上进行部署,这个时候就需要将此镜像进行备份。#语法 docker save -o 导出的文件名 镜像名如下,我们将镜像 mynginx_i 镜像保存为 mynginx.tar 文件;[root@192 ~]# docker save -o mynginx.tar mynginx_i [root@192 ~]# dir anaconda-ks.cfg html mynginx.tar [root@192 ~]# 3. 镜像恢复与迁移将镜像保存为 .tar 文件后就可以将它放到其他服务器进行部署了,首先将其恢复;#语法 docker load -i 文件名首先我们的系统中是没有 mynginx_i 镜像的;[root@192 ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest 605c77e624dd 6 months ago 141MB redis latest 7614ae9453d1 6 months ago 113MB mysql latest 3218b38490ce 6 months ago 516MB centos 7 eeb6ee3f44bd 9 months ago 204MB centos/mysql-57-centos7 latest f83a2938370c 2 years ago 452MB tomcat 7-jre7 47c156f4d4e3 3 years ago 359MB [root@192 ~]# 接下来使用 mynginx.tar 文件将其恢复,再次查看镜像;[root@192 ~]# docker load -i mynginx.tar b5d12f59f6a7: Loading layer 18.94kB/18.94kB Loaded image: mynginx_i:latest [root@192 ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE mynginx_i latest 42b5d8d237eb 45 minutes ago 141MB nginx latest 605c77e624dd 6 months ago 141MB redis latest 7614ae9453d1 6 months ago 113MB mysql latest 3218b38490ce 6 months ago 516MB centos 7 eeb6ee3f44bd 9 months ago 204MB centos/mysql-57-centos7 latest f83a2938370c 2 years ago 452MB tomcat 7-jre7 47c156f4d4e3 3 years ago 359MB [root@192 ~]# 二、Dockerflie1. 认识 DockerfileDockerfile 是由一系列的命令和参数构成的脚本,这些命令用于基于一个基础镜像来构建一个新的镜像。基础镜像:Ubuntu、CentOS 等操作系统级别的镜像。比如在 CentOS 系统上安装了一个 JDK,那么 CentOS 镜像 就是 JDK 的基础镜像;后续在 JDK 的基础上又安装了其他的微服务,那么 JDK 镜像就是微服务的基础镜像。对于开发人员来说,Dockerfile 可以为开发团队提供一个完全一致的开发环境;对于测试人员来说,可以直接拿开发时所构建的镜像或者 Dockerfile 文件构建一个新的镜像开始工作;对于运维人员来说,部署时可以实现应用的无缝移植。Dockerfile 的主要目的就是更方便的构建镜像文件,避免过多的重复与出错。2. Dockerfile 常用命令3. 使用 Dockerfile 构建镜像此处我以构建 JDK 1.8 镜像为例,基础镜像为 CentOS 7。第一步,创建一个目录,用于存放镜像;[root@192 ~]# mkdir -p /usr/local/dockerjdk8 [root@192 ~]# 第二步,上传 jdk 压缩包至该目录;[root@192 ~]# cd /usr/local/dockerjdk8 [root@192 dockerjdk8]# ls jdk-8u261-linux-x64.tar.gz [root@192 dockerjdk8]# 第三步,构建 Dockerfile 文件;[root@192 dockerjdk8]# vi Dockerfile #文件内容 #指定基础镜像 FROM centos:7 #指定镜像创建者 MAINTAINER Developer_xiaoma #设置当前目录 WORKER /usr #创建一个目录 RUN mkdir /usr/local/java #添加压缩包 ADD jdk-8u261-linux-x64.tar.gz /usr/local/java/ #添加环境变量. ENV JAVA_HOME /usr/local/java/jdk1.8.0_261 ENV JRE_HOME $JAVA_HOME/jre ENV CLASSPATH $JAVA_HOME/bin/dt.jar:$JAVA_HOME/lib/tools.jar:JRE_HOME/lib:$CLASSPATH ENV PATH $JAVA_HOME/bin:$PATH 第四步,构建镜像;[root@192 dockerjdk8]# docker build -t='jdk1.8' . # -t 指定镜像名称 # . 代表当前目录,会自动到当前目录寻找 Dockerfile 文件构建成功如下:        第五步,查看结果,构建完成后 docker images 查看 Docker 下的镜像;[root@192 dockerjdk8]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE jdk1.8 latest 15c81e18c22e 2 minutes ago 556MB mynginx_i latest 42b5d8d237eb 6 hours ago 141MB nginx latest 605c77e624dd 6 months ago 141MB redis latest 7614ae9453d1 6 months ago 113MB mysql latest 3218b38490ce 6 months ago 516MB centos 7 eeb6ee3f44bd 9 months ago 204MB centos/mysql-57-centos7 latest f83a2938370c 2 years ago 452MB tomcat 7-jre7 47c156f4d4e3 3 years ago 359MB [root@192 dockerjdk8]# 可以看到,jdk1.8 创建成功,演示完成。
0
0
0
浏览量246
锅从天上来

【云服务器 ECS 实战】负载均衡 SLB 概述及配置选型

一、初识负载均衡 SLB1. 负载均衡概述负载均衡就是将访问流量根据转发策略分发到后端的多台服务器中。负载均衡建立在现有网络结构之上,提供一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。简单理解就是将负载(工作任务)进行平衡并分摊到多个操作单元上进行执行。2. 为什么要使用负载均衡原因一:实现承载高并发、提高处理性能在实际的企业业务中,随着业务量、用户及服务量的不断累加,仅靠单台 ECS 云服务器是无法满足其业务需要的,而对这些海量 高并发 的处理就需要使用到负载均衡,将这些海量的流量分发至后台的多台服务器进行处理。高并发(High Concurrency):系统运行过程中遇到的一种“短时间内遇到大量操作请求”的情况,诸如大量的用户访问等。原因二:高可靠性,实现后端服务冗灾所谓高可靠性,就是当只有一台服务器时,如果该服务器出现了任何故障,那么就会直接影响整个网站的无法服务。负载均衡技术的好处在于可以设置固定的健康检查模式,对后端服务进行定期检查,同时使用多台服务器对外提供访问服务,某一台服务器出现故障时则可以通过负载均衡 LSB 动态的将这台故障服务器移除,以至于不会影响整个网站的运行。二、ECS 传统型负载均衡 CLB 服务的配置与创建首先进入阿里云服务器 ECS 控制台,选择“实例” --> “管理”,进入实例详情页;在实例详情的最下面有“关联的负载均衡”模块,我们点击进入负载均衡控制台;在控制台中,选择传统型负载均衡下的“实例管理”,可进行传统型负载均衡 CLB 的创建;针对可用区的选择:可用区指的是一套独立的基础设施,不同的可用区之间基础设施(网络,电力和空调等)相互独立,即一个可用区出现基础设施故障不影响另外一个可用区。选择 多可用区 模式负载均衡服务可以更加可靠,当主可用区的机房故障或不可用时,负载均衡仍然有能力在非常短的时间内(约 30s)切换到另外一个备可用区的机房并恢复服务的能力;当主可用区恢复时,负载均衡同样会自动切换到主可用区的机房提供服务。我们在选择可用区时需要先看自己需要设置负载均衡的实例是在哪个可用区,如下我的实例是位于华北 2,北京可用区 H;所以我在负载均衡的可用区中选择与实例相对应的,而备可用区默认即可;针对阿里云负载均衡服务的收费模式的选择:有 按规格计费 和 按使用量计费 两种。按规格计费模式每小时的规格费将按用户购买时所选规格固定收取,适用于满足部分用户对固定使用量有强诉求的业务场景;对于业务峰值变化较大的用户而言,按使用量计费可以更好的兼顾成本与业务可用性。如下是两种计费方式对比:针对实例类型的选择:公网 是对外部用户提供服务的,私网 则只对阿里云内部服务提供访问,我们根据自己需要进行选择。选择相关参数之后,点击“立即购买”;开通成功之后回到负载均衡控制台,可以看到已有传统型负载均衡实例,至此负载均衡 CLB 服务创建成功。
0
0
0
浏览量2015
锅从天上来

【云原生 • Kubernetes】一文掌握 k8s 包管理工具 Helm

一、为什么要引入 Helm1. Helm 的应用场景在以往的应用部署过程当中,我们需要先编写一个 yaml 文件,然后该文件中包含 deployment、Service、Ingress 等等。如果说需要部署的是单一、少数服务的应用,那么完全可以使用 yaml 文件的方式,这样会很简单。但是在实际的项目当中,微服务的数量基本不可能是一个,可能是几十个,如果说再用 yaml 文件的部署方式,那就意味着需要编写几十个 yaml 文件,这就会导致 数量多、维护难 等诸多问题。2. 使用 Helm 可以解决哪些问题针对上述问题,Helm 的引入使用则可以将所有的 yaml 文件进行一个整体的管理,而且它能够实现 yaml 文件的高效复用。高效复用:yaml 文件的格式和结果基本相同,一般只是属性值有所变化。使用 helm 后,针对格式和结构基本相同的 yaml 文件就不需要一遍一遍的进行重复编写了,直接复用即可。 除此之外,Helm 还可以进行应用级别的版本管理,包括版本更新、回退等等。二、Helm 概述Helm 是 Kubernetes 的一个 包管理工具,类似于 Linux 下的包管理工具如 yum、apt 等。可以方便的将之前打包好的 yaml 文件部署到 Kunernetes 上。在 Helm 中有三个主要概念:在 2019 年 11 月 13日,Helm 团队发布了稳定版本 Helm v3,这也是当前主流版本。该版本与往期版本相比较有主要以下变化:删除了 Tiller;支持 release 在不同命名空间中重用;支持直接将 Chart 推送到 docker 仓库中。如下为各版本 Helm 架构简易示意图。v3 之前版本架构v3 版本架构三、Helm 安装与配置(v3)1. 安装 Helm v3第一步:前往 Helm 官网下载压缩文件;也可以直接使用以下网址进行下载,我这里使用的是 3.0.0 版本:第二步:将压缩文件上传至我们的 Linux 系统;第三步:解压 helm 压缩文件;#解压文件 tar -zxvf helm-v3.0.0-linux-amd64.tar.gz解压后会有一个 linux-arm64 目录,这其中就包含了我们需要的 helm 文件;第四步:将解压之后的 helm 目录复制或者移动到 /usr/local/bin 目录下;#移动文件 mv helm /usr/local/bin完成此四步的操作之后就可以直接在 Linux 系统中使用 helm 命令进行相关操作了,如果使用 helm 命令不报错,则说明 helm 安装成功。2. 配置 Helm 仓库添加仓库语法如下;#语法 helm repo add 仓库名称 仓库地址 #eg: #添加微软仓库 helm repo add stable http://mirror.azure.cn/kubernetes/charts #添加阿里云仓库 helm repo add aliyun https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts仓库成功添加之后可以使用 helm repo list 命令查看已有仓库;四、使用 Helm 快速部署应用在这里我们以部署可视化工具 weave 为例。第一步:使用命令搜索应用 weave;helm search repo weave第二步:根据搜索到的内容选择安装;#安装 helm install ui stable/weave-scope这里选择的是微软源的 weave-scope 进行安装,如果在安装过程中报错那就换一个源;安装成功就可以使用命令 helm list 查看了;接下来使用 kubectl get pods 和 kubectl get svc 就可以看到我们安装的 weave 相关内容和对外暴露端口;第三步:可以看到此时并未对外暴露端口,所以我们需要修改 service 中的 yaml 文件,将 type 值改为 NodePort,使用命令 kubectl edit svc ui-weave-scope;修改过后再次查看 svc,此时已有端口暴露;五、自定义 Chart 部署应用我们在这里以部署自定义应用 myweb1 为例。第一步:创建一个chart;helm create mychart创建成功会自动生成一个 mychart 目录(其实也就是一个模板);在生成的目录中有以下几部分:第二步:进入 templates 目录,创建 deployment. yaml 文件;[root@master mychart]# cd templates/ [root@master templates]# kubectl create deployment myweb1 --image=nginx --dry-run -o yaml > deployment.yaml W0906 10:18:15.827722 113157 helpers.go:535] --dry-run is deprecated and can be replaced with --dry-run=client. [root@master templates]# ls deployment.yaml ingress.yaml serviceaccount.yaml tests _helpers.tpl NOTES.txt service.yaml查看 deployment.yaml 文件;第四步:设置对外暴露端口,创建 service.yaml 文件;[root@master templates]# kubectl expose deployment myweb1 --port=80 --target-port=80 --type=NodePort --dry-run -o yaml > service.yaml W0906 10:37:13.004600 126020 helpers.go:535] --dry-run is deprecated and can be replaced with --dry-run=client. [root@master templates]# ls deployment.yaml ingress.yaml serviceaccount.yaml tests _helpers.tpl NOTES.txt service.yaml如果这里无法导出,我们就先创建一次镜像:kubectl create deployment myweb1 --image=nginx; 导出 service 后再删除此镜像:kubectl delete deployment myweb1查看 service.yaml 文件;此时在 templates 目录中已有创建的两个 yaml 文件;第五步:回到 mychart 父级目录,开始安装;[root@master linux-amd64]# helm install myweb1 mychart/安装成功后查看应用内容,应用节点与对外端口均创建成功;myweb1 应用部署完成,此时就完成了 chart 的自定义及部署应用操作。第六步:应用升级,每次修改 yaml 文件内容之后,我们均需对应用进行升级操作,使用如下命令。#格式 helm upgrade 自定义应用名称 目录 #eg: helm upgrade myweb1 mychart/六、Helm 实现 yaml 文件高效复用高效复用:如果若干 yaml 文件的格式和结果基本相同,只是属性值有所变化时。在使用 Helm 后,针对格式和结构基本相同的 yaml 文件就不需要一遍一遍的进行重复编写了,直接复用即可。其主要实现原理就是通过动态传递参数、动态渲染模板、动态传入参数生成 yaml 文件内容。创建 chart 之后,目录下有一个 values.yaml 文件,基于此进行操作;第一步:在 values.yaml 文件中定义全局变量和值;第二步:在具体的 yaml 文件中获取定义的变量值。原理就是以表达式的形式获取全局变量,格式为:{{ .Values.变量名称}}此处以修改 deployment.yaml 文件为例:修改后如下:apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: app: myweb1 name: {{ .Release.Name}}-deploy spec: replicas: 1 selector: matchLabels: app: {{ .Values.label}} strategy: {} template: metadata: creationTimestamp: null labels: app: {{ .Values.label}} spec: containers: - image: {{ .Values.image}} name: nginx resources: {} status: {} 七、Helm 的常用操作命令汇总#查看仓库 helm repo list #更新仓库 helm repo update #删除仓库 helm repo remove 仓库名称 #搜索应用 helm search repo 名称 #安装应用 helm install 自定义应用名称 搜索出的结果名 #查看安装后的应用 helm list helm status 应用名称 #创建chart helm create chart名称
0
0
0
浏览量2009
锅从天上来

【云原生 • Kubernetes】kubernetes 核心技术 - 持久化存储

一、nfs 网络存储1. master 节点部署 nfs(nfs 服务端)首先我们需要将一台虚拟机/服务器作为 nfs服务器,并安装 nfs、设置挂载路径。在这里我使用 master 节点虚拟机 【k8s_master】 作为 nfs 服务器,IP 地址为 192.168.200.132;第一步:安装 nfs;yum install -y nfs-utils第二步:设置挂载路径,vi /etc/exports 进入文件,在该文件中加入以下内容;我这里挂载的是 /data/nfs 目录(可自定),* 代表所有内容,rw 代表授予读写权限;第三步:创建要挂载的目录 /data/nfs,如果不创建目录后面会报错找不到该目录;[root@master ~]# mkdir data [root@master ~]# cd data [root@master data]# mkdir nfs [root@master data]# ls nfs [root@master data]# 此时,nfs 服务端部署完成。2. node 节点部署 nfs在 k8s 集群中代表 node 节点的虚拟机/服务器中也安装 nfs;提示:k8s 集群的完整搭建过程均已在往期文章讲述,文章之间内容环环相扣,详情请参见专栏 云原生 - 入门到实战。在这里我使用 node 节点虚拟机【k8s_node1】和【k8s_node2】,IP 地址分别为 192.168.200.133、192.168.200.134;3. 网络存储验证演示第一步:在 nfs 服务端(master 节点)启动 nfs;systemctl start nfs启动之后可以使用命令 ps -ef | grep nfs 查看 nfs 进程;第二步:新建一个目录 pv 和 yaml 文件 nfs-nginx.yaml;[root@master ~]# mkdir pv [root@master ~]# cd pv [root@master pv]# vi nfs-nginx.yamlyaml 文件中写入以下内容:apiVersion: apps/v1 kind: Deployment metadata: name: nginx-dep1 spec: replicas: 1 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx volumeMounts: - name: wwwroot mountPath: /usr/share/nginx/html ports: - containerPort: 80 volumes: - name: wwwroot nfs: server: 192.168.200.132 path: /data/nfs第三步:在 yaml 文件创建成功后执行该文件;[root@master pv]# kubectl apply -f nfs-nginx.yaml deployment.apps/nginx-dep1 created [root@master pv]# 如果启动文件时报错请先关闭系统的防火墙 service iptables stop。此时查看 pods 可以看到我们创建的 nginx-dep1,为 running 状态即创建成功;第四步:进入 nginx-dep1kubectl exec -it nginx-dep1-6f58f9944b-zz25r bash接下来就可以使用我们在 yaml 文件中挂载的目录 /usr/share/nginx/html 了;开始查看该目录一定是为空的,当我们 nfs 目录下创建任何文件时,文件都会存储在此挂载目录,且是持久化存储。二、PV 和 PVC1. PV、PVC 介绍在网络存储的方式中,我们必须要知道 nfs 服务器的 IP 地址,那么如若 IP 地址泄露,安全则不能被保障,所以该方法弊端明显。而 PV 和 PVC 则可以解决该弊端:PV:PersistentVolume 持久化存储,对存储资源进行抽象,可以对外提供一个专门用于调用的接口(生产者)。PVC:PersistentVolumeClaim 持久化存储调用,用户调用无需关系内部实现细节,直接调用即可(消费/调用者)。2. 实现流程第一步:在 pv 目录下创建 pv.yaml 文件,写入以下内容;apiVersion: v1 kind: PersistentVolume metadata: name: my-pv spec: capacity: storage: 5Gi accessModes: - ReadWriteMany nfs: path: /k8s/nfs server: 192.168.200.132第二步:在 pv 目录下创建 pvc.yaml 文件,写入以下内容;apiVersion: apps/v1 kind: Deployment metadata: name: nginx-dep1 spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx volumeMounts: - name: wwwroot mountPath: /usr/share/nginx/html ports: - containerPort: 80 volumes: - name: wwwroot persistentVolumeClaim: claimName: my-pvc apiVersion: v1 kind: PersistentVolumeClaim metadata: name: my-pvc spec: accessModes: - ReadWriteMany resources: requests: storage: 5Gi第三步:执行 yaml 文件;kubectl apply -f pv.yaml kubectl apply -f pvc.yaml之后的操作则与 nfs 相同,区别在于此方法多了一层 PVC。
0
0
0
浏览量2012
锅从天上来

【云原生 • Kubernetes】一文深入理解资源编排 - yaml 文件

1. yaml 文件概述Kubernetes 集群中对资源管理和资源对象的编排部署可以通过声明样式(yaml)文件的方式来解决,把需要对资源对象的操作都编辑到 yaml 格式的文件中,这种文件叫做 资源清单文件。通过 kubectl 命令可以直接使用资源清单文件实现对大量的资源对象进行编排和部署。2. yaml 文件书写格式yaml 的可读性非常高,它是用来表达 数据序列 的格式。它本身仍是一种 标记语言,但这种语言是以数据为中心,而不是以标记语言为中心。yaml 文件基本语法如下:使用空格作为缩进;缩进的空格数自定,但要求相同层级的元素左侧对齐;一般开头缩进两个空格,字符后面也要缩进一个空格;低版本缩进时不能用 Tab 键,只能用空格键;使用 # 标识注释,从这个字符处开始到行尾,都会被解释器忽略;使用一个 - 代表普通的格式,使用三个 - 则代表以下开始书写新的 yaml 文件。3. yaml 文件组成部分及字段含义通常在一个完整的 yaml 文件中,包含两个部分,控制示例 和 被控制的对象。文件中必须存在的属性有如下几个:如下是一个最基本的完整的 yaml 文件模板:#第一部分:控制器示例 apiVersion: apps/v1 kind: Deployment metadata: name: nginx namespace: default spec: replicas: 3 selector: matchLabels: app: nginx #第二部分:被控制的对象 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx ports: - containerPort: 804. 如何快速编写 yaml 文件在实际开发过程中,如果说让我们从零开始编写一个完整的 yaml 文件出来,还是有一定难度的,至少字段以及格式上就很难保证不出错。手写是不现实的,所以我们通常需要通过一定的方式 快速生成yaml文件:• 方法一:kubectl create 生成如下,我使用 kubectl create 命令创建一个名为 web 的 deployment 资源,但是不让它真正创建,而是生成一个 yaml 文件;kubectl create deployment web --image=nginx -o yaml --dry-run–dry-run:尝试运行,不真正运行。运行结果如下:可以看到 yaml 文件已经生成,包含了所有字段以及格式,之后对它进行复制修改即可。此过程并未在集群中执行,而仅仅是以 yaml 文件的形式输出了,我们索取需要的文件内容和格式即可。为了更加方便,我们也可以直接将生成的 yaml 文件内容输入到某一个文件当中,之后修改文件内容,如下;kubectl create deployment web --image=nginx -o yaml --dry-run > ma.yaml• 方法二:kubectl get 导出此方法适用于已经部署好的项目中,将项目中的 yaml 文件导出。在这里我先查看以下集群中已经部署的项目资源;以操作 nginx 资源为例,将 nginx 资源相关内容以 yaml 格式导出并输入到 ma2.yaml 文件中,命令如下:kubectl get deploy nginx -o=yaml --export > ma2.yaml执行结果如下,ma2.yaml 文件已生成:
0
0
0
浏览量1041
锅从天上来

如火如荼的「云原生」,你了解多少?

一、什么是云原生?“云” 表示应用程序位于云(即云服务器)中,而不是传统的应用数据中心。“原生” 可以理解为 “土生土长”,指一出生便有这个大环境,如互联网原住民从一出生就有已经有互联网环境的存在。云原生(Cloud Native)是基于微服务原理而开发的应用,以容器的方式进行打包。在运行时,容器由运行于云基础设施之上的平台进行调度。应用开发采用持续交付和 DevOps 实践。总结来说云原生就是基于云计算而来的技术,对云计算技术的不断精进和细化。云原生架构则是开发云原生应用所用到的架构,核心有两点:一是应用要以微服务的方式进行构建、二是应用架构方式一开始就要面向容器云部署。二、“云”演进史🕛 2000 年以前,还没有虚拟化技术,企业计算直接采用硬件服务器。当时 sun 公司就是专门提供中高端的企业应用服务器。🕐 2001 年,VMware 推出了虚拟化技术,可以使用软件方式按需创建虚拟机,之后的时间里 VMware 一直是虚拟化技术的行业领导者。🕑 2006 年,亚马逊研发了 Iaas(基础设施即服务),此技术将计算网络存储封装成了可以按需使用的资源,基于此亚马逊将 Iaas 进行商业化,推出了 AWS 公有云,直至今日 AWS 仍是公有云行业龙头。🕒 2009 年,HEROKU 推出了商业化平台 Paas(平台即服务),抽象层次高于 Iaas,用户可以直接在 Paas 部署应用,无需关心底层计算资源。HEROKU 可认为是现代云原生平台的鼻祖。🕓 2010 年,行业出现了开源的 Iaas 产品,主要满足了一些中大型企业自建私有云的需求。🕔 2011 年,行业出现了开源的 Paas 平台。🕕 2013 年,docker 容器技术诞生并从一开始就走上了开源路线,使得容器化在行业得到了快速普及。🕖 2015 年,随着 docker 等技术的普及,谷歌、微软等大厂开始了立标准的过程,成立了 Cloud Native computing foundation(CNCF),旨在推动云原生项目的治理、推广和应用,标志着云原生时代的到来。三、云原生核心技术及概念1. 微服务传统的大的单体应用拆分为更小的组件或者模块,这个组件或者模块就叫微服务。拆分为纵向拆分,从底层的 IT 基础设施到数据库,到应用中间件,再到软件程序部署包都能做到完全独立,可以单独的进行需求设计、开发、打包和部署,实现各个微服务之间一个彻底的松耦合。同时各个微服务之间又能够通过轻量的 HTTP rest 接口进行交互和协同。总结来说微服务的核心为两点:大的单体拆小、拆小的微服务之间通过接口进行交互和协同。2. DevOpsDevOps 是一组过程、方法与系统的统称,用于促进开发、技术运营、质量保障(QA)部门之间的沟通、协作与整合。可以理解为持续集成和持续交付,将软件生命周期过程中的需求分析到程序设计、开发、编译、构建、打包和部署,从测试环境到生产环境整个过程实现全部的自动化。3. 容器云容器云的核心有两个,一个是 Docker 容器、一个是 Kurbernetes 的容器资源调度和编排。容器本身是一个比虚拟机更轻量化的资源隔离单位。区别在于虚拟机是独享一个操作系统,而容器是架在操作系统之上的,多个容器可以共享操作系统。体积要比虚拟机小且创建、销毁、调度的速度也比传统虚拟机快。但容器本身是一个 Iaas 层的内容,需要结合 Kubernetes 来向上层 Paas 层提供服务能力。4. 服务网格服务网格就是一个去中心化的服务治理框架。在以往的操作中对微服务或 API 接口进行治理和管控时,一般会用类似于 esb 总线、API 网关的设施,将 API 接口注册和接入到 API 网关。API 网关本身是一个中心化的架构,所以所有的请求、流量都可以通过 API 网关,这时 API 网关就容易对流量进行拦截,然后对拦截的流量进行管控。而在去中心化的架构中就没有这种集中化的流量管控了,对于流量的拦截,会从 esb 总线或者 API 网关下沉到各个微服务当中,这时需要在微服务端增加一个代理包,通过代理包做流量拦截和流量管控。5. Serverless 无服务器架构“无服务器” 即几乎不接触 IT 基础设施。要知道云原生的核心就是要实现从资源到服务不断的向上抽象,在这个抽象的过程中 IT 基础设施的接触则会越来越少,接触更多的是各种技术服务能力。这些技术服务能力在 Serverless 架构中称为 Baas 后端能力及服务。Serverless 对于开发流程有着很大的改变:传统开发流程(前端工程师、后端工程师、运维工程师)设计 → 服务端/前端开发 → 服务端部署 → 前后端联调 → 测试 → 上线 → 运维Serverless 开发流程(前端工程师、后端工程师)设计 → 应用开发 → 测试 → 上线可以看到 Serverless 无服务器化以后,一些重的开发框架、环境、多层架构等都被抛弃掉了,此时任何一个功能的实现全部变成一个个代码片段(只需要写一些函数,开发较为简单),然后通过代码片段的组合安装来实现复杂的流程。6. 不可变基础设施传统软件部署中,当程序部署到一个生产环境或者 tomcat 中间件以后,如果需要去做变更,无论任何变更都需要在原来的生产环境上进行重新部署。而在云原生的概念中强调任何一个应用部署到生产环境,形成一个容器实例之后,这个容器实例本身不应该再做任何的变化,如果程序需要修改,则基于容器镜像重新去生成一个容器实例,同时销毁旧的容器实例。7. 声明式 API声明式 API 是和命令式 API 相对应的一个概念,传统方式创建或者操作一个容器需要去执行一个命令行。但是在声明式 API 中,对于容器的创建,首先应该先写一个 yaml 配置文件,在这个配置文件当中声明出要做的操作和操作完成之后的状态,然后平台底层拿到这个声明式配置文件之后,解释该文件内容,做出相应的后端操作,操作结束之后将各个底层的技术组件协调到需要的状态。这样的操作流程便于生产环境出现问题时快速找到自己所做了什么操作。四、云原生对程序员来说意味着什么?距字节跳动 | 火山引擎副总经理张鑫介绍,云原生为程序员带来的首先是编程范式的改变,以往从开发到编译、测试、发布,都有着一整套的流程和体系,云原生的到来则定义了一种新的规范,程序员就需要掌握一种新的技能。其次也是最重要的就是思维模式的改变,以前写软件会想着怎么把他运行在一个 Server 服务器上,k8s 云原生出现以后从一开始设计的时候就需要考虑到未来将它运行到一个可扩展性、可弹性自动化管理的云端。五、云原生对 IT 岗位会有什么样的影响?云原生对 IT 岗位的影响是全方位并且深入的,所以人人去学云原生也是必要的。技术栈:后端研发需要关注大量用到的技术,比如容器、微服务、Serverless、Paas 云服务等;分布式设计模式:云原生技术体系包含了大量已经存在的分布式设计模式;业务开发:云原生技术和云服务采用的越多,开发人员在非功能特性开发方面花费的经历就越少,从而有更多的时间关注业务本身的功能性设计;测试方式:传统是基于预测来设计测试案例的方式进行测试,这样效率太低,解决方式是利用主动故障注入和馄饨工程进行疲劳测试,真实模拟现实世界可能发生的故障;软件研发和运维流程:DevOps 和 DevsecOps 不仅要求企业做到安全的持续发布,还要求企业重新定义和规范开发人员接触的研发流程和工具,实现开发运维岗位一体化;
0
0
0
浏览量2014
锅从天上来

【云原生 • Kubernetes】kubernetes 核心技术 - Label 和 Select

1. Label 概述Label(标签) 是 Kubernetes 的一个核心概念。一个 Label 就是一个 key:value 的键值对被关联到对象上,其中 key 与 value 由用户自己指定。"labels": { "key1" : "value1", "key2" : "value2" }标签的使用使得我们能标识出对象的一些特殊特点,比如说标识了某个 Pod,那么用户就可以一眼看出这个 Pod 是干什么的。标签可以用来划分特定组的对象,可以在创建一个对象的时候直接给与,也可以在后期动态添加或删除,每一个对象可以拥有多个标签,但是 key 值必须是唯一的。Label 也可以附加到各种资源对象上,如 Node、Pod、Service、RC,一个资源对象可以定义任意数量的 Label,同一个 Label 也可以被添加到任意数量的资源对象上。2. Label 语法规则语法格式:key: value(键值对)Key:不超过 63 个字符 支持使用前缀,前缀必须是 DNS 子域,不超过253个字符。 系统化组件创建的 label 必须指定前缀。kubernetes.io 和 k8s.io 由 kubernetes 保留 格式:[A-Za-z0-9][A-Za-z0-9_-.]value:不超过 63 个字符 格式:[A-Za-z0-9][A-Za-z0-9_-.]3. Label 的定义Label 最常见的用法是使用 metadata.labels 字段来为对象定义 Label,使用 spec.selector 字段来引用对象。如下:#添加Label apiVersion: v1 kind: Pod metadata: name: nginx labels: app: new_nginx #定义Label:new_nginx#引用label apiVersion: v1 kind: Pod metadata: name: nginx spec: replicas: 1 selector: app: new_nginx #引用刚刚定义的Label:new_nginxLabel 附加到 Kubernetes 集群中的各种资源对象上,目的就是对这些资源对象进行分组管理,而分组管理的核心正是 Label Selector。需要知道 Label 与 Label Selector 都不能单独定义,必须附加在一些资源对象的定义文件上,一般是附加在 RC 和 Service 的资源定义文件中的。4. Label 常用命令查看标签kubectl get pod nginx -n dev --show-labels为 Pod 资源打标签#为名为nginx的pod添加label aaa=bbb kubectl label pod nginx aaa=bbb -n dev为 Pod 资源更新标签#将名为nginx的pod的label修改为ccc=ddd,且覆盖现有的value kubectl label pod nginx ccc=ddd -n dev --overwrite筛选标签kubectl get pod -n dev -l eee=fff --show-labels删除标签#删除nginx中名为aaa的label kubectl label pod nginx aaa- -n dev
0
0
0
浏览量1741
锅从天上来

【云原生 • Docker】mysql、tomcat、nginx、redis 环境部署

一、MySQL 部署1. 拉取 MySQL 镜像,此处选择的是 MySQL 5.7 版本;docker pull centos/mysql-57-centos72. 创建容器,容器名称为 mysql;docker run -di --name=tensquare_mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql-p 表示端口映射关系,格式为 宿主机映射端口 : 容器运行端口;-e 表示添加环境变量,此处设置 root 用户登录密码为 123456。如下即为创建成功:3. 远程登录 MySQL容器创建完成之后,就可以在本地进行 MySQL 连接了;如下图在本地的 Navicat 中新建一个连接:要知道我们并不是直接去连接容器中的 MySQL,而是通过宿主机进行连接。此时所连接的正是我们刚刚所创建的容器中的 MySQL;Docker 下 MySQL 部署完成!二、Tomcat 部署1. 拉取 tomcat 镜像;docker pull tomcat:7-jre72. 创建容器;docker run -di --name=mytomcat -p 9000:8080 -v /usr/local/webapps:/usr/local/tomcat/webapps tomcat:7-jre7-v  目录映射关系,前者为宿主机目录,后者是映射到宿主机上的目录,如果没有该目录会自动创建-p  端口映射关系,前者为宿主机端口,后者是容器内的映射端口3. 部署应用容器创建成功之后,我们这时直接在本地访问是没有效果的,报错 404;这是因为我们使用到了目录挂载,本地的目录 /usr/local/webapps 是新创建的,没有任何应用,所以访问时无显示。这时候我们可以为它部署一个应用,也就是往此目录中放入一个应用,我在这里用了一个简单的测试 war 包 cluster_test.war(文末附下载地址);上传后如下,目录中出现 war 包和自动解压后的文件;成功部署后就可以在本地进行访问了,如下访问成功,不再报错;Docker 下 tomcat 部署完成!需要注意在 tomcat 部署过程当中,如部署后无法正常访问,报错 404,这说明 tomcat 服务是没问题的。那么无法正常访问可能有三个原因:防火墙未开放该端口;访问路径写的有问题;war 包本身有问题;三、Nginx 部署1. 拉取 nginx 镜像docker pull nginx2. 创建容器docker run -di --name=mynginx -p 80:80 nginx创建成功我们在本地浏览器访问宿主机 IP,可以看到 nginx 欢迎界面;3. 部署应用我们这里将一个静态页面部署到 nginx 中,如下我在本地创建了一个 html 文件夹 和 index.html 文件;将它上传至我们的宿主机;进入 nginx 容器;docker exec -it mynginx /bin/bash找到配置文件 default.conf,可以看到 nginx 的页面文件是保存于 /usr/share/nginx/html/ 中的;所以我们将需要部署的页面文件移动到此目录;docker cp html mynginx:/usr/share/nginx/此时再次在本地访问宿主机 IP,页面显示已由 nginx 欢迎页面变成了我们部署的页面;Docker 下 nginx 部署完成!四、Redis 部署1. 拉取镜像docker pull redis2. 创建容器docker run -di --name=myredis -p 6379:6379 redis3. 测试使用本地的 redis(文末附下载地址) 进行测试,如下图;在 redis 目录下打开终端,redis-cli -h 宿主机IP 连接宿主机;连接成功,占用 6379 端口且可正常运行;Docker 下 redis 部署完成!
0
0
0
浏览量2019
锅从天上来

【云原生 • DevOps】一文掌握容器管理工具 Rancher

一、容器管理工具 Rancher 介绍Rancher 是一个开源的企业级全栈化容器部署及管理平台,其实就是一个 Docker 的图形化管理界面。它为容器提供基础架构服务,可以让 CNI 兼容的网络服务、存储服务、主机管理、负载均衡、防火墙等服务跨越公有云、私有云、虚拟机、物理机环境运行,真正实现一键式应用部署和管理。除此之外它还提供了诸如负载均衡、弹性扩容等高级功能,也是一个比较常用的运维工具。提示:由于 Rancher 是 Docker 的界面化操作,比如应用部署等操作其实都是重复的,为避免端口互相冲突,所以建议在一个新的系统镜像中进行操作。二、Rancher 的安装第一步:下载 Rancher 镜像;docker pull rancher/server第二步:创建 Rancher 容器;docker run -di --name=rancher -p 9090:8080 rancher/server第三步:本地浏览器输入 虚拟机/服务器 IP:端口号 进行访问,看到如下界面即 Rancher 安装成功;如果访问不了看看自己创建的容器是否已启动。初始界面为英文界面,可在右下角切换中文;三、Rancher 的初始化1. 添加环境Rancher 支持将资源分组归属到多个环境,每个环境都有着自己独立的基础架构资源及服务,并由一个或者多个用户、团队/组织管理。比如说:你可以创建独立的开发、测试及生产环境并确保这些环境之间的安全隔离,将开发环境的访问权限授予全部人员,而测试环境仅允许某个小的团队访问。点击 “Default” --> “环境管理”,进入环境界面;点击“添加环境”,输入环境名称和描述即可创建;如下是我创建的开发、生产、测试环境,每个环境完全分离,在环境上的配置也不会互相影响;此时选择 “Default” 可以进行环境间的切换;2. 添加主机选择 “基础架构” --> “主机”,点击添加主机;默认选择的是我们的虚拟机/服务器的站点地址,点击保存;之后会进入如下界面;注意第五步中的代码,该代码表示创建一个 Rancher 代理容器,在需要添加 Rancher 服务的虚拟机/服务器上运行此命令,则虚拟机/服务器便会和 Rancher 服务建立联系。复制该代码,在需要连接 Rancher 服务的虚拟机/服务器上运行,运行成功如下;此时在 Rancher 的主机界面会增加一个主机;3. 添加应用此处的应用其实就是指我们的某个项目,而某个项目下面又包含着多个服务,换句话说应用其实就是服务的分组;点击 “应用” --> “全部/用户”,然后点击 “添加应用” 按钮;输入名称和描述后点击 “创建”;成功后如下;应用创建成功之后,就可以在应用上部署服务了,也就是应用部署。四、应用部署其实在 Rancher 中部署应用与传统方式(命令行操作)最大的区别就在于在这里所有操作都是在图形界面中进行的,更为直观,请看以下部署演示。1. Mysql 部署首先下载镜像 centos/mysql-57-centos7 增加数据库服务;[root@192 ~]# docker pull centos/mysql-57-centos7 Using default tag: latest latest: Pulling from centos/mysql-57-centos7 d8d02d457314: Pull complete a11069b6e245: Pull complete 596303fb1aa3: Pull complete a29499e779a7: Pull complete 17d1a52c2e00: Pull complete ed24591227fe: Pull complete de0ad46e3ed9: Pull complete c62e4a984a9c: Pull complete 01d54c6bda68: Pull complete Digest: sha256:e08ee4d43b7356607685b69bde6335e27cf20c020f345b6c6c59400183882764 Status: Downloaded newer image for centos/mysql-57-centos7:latest docker.io/centos/mysql-57-centos7:latest [root@192 ~]# 然后在我们创建好的应用中,点击 “添加服务”;此时就可以以图形化界面的方式来部署 MySQL 服务了,进行相关的设置;点击 “创建”,显示 “Active” 则说明部署成功;2. RabbitMQ 部署下载镜像 rabbitmq:management;[root@192 ~]# docker pull rabbitmq:management management: Pulling from library/rabbitmq 7b1a6ab2e44d: Pull complete 37f453d83d8f: Pull complete e64e769bc4fd: Pull complete c288a913222f: Pull complete 12addf9c8bf9: Pull complete eaeb088e057d: Pull complete b63d48599313: Pull complete 05c99d3d2a57: Pull complete 43665bfbc3f9: Pull complete f14c7d7911b1: Pull complete Digest: sha256:4c4b66ad5ec40b2c27943b9804d307bf31c17c8537cd0cd107236200a9cd2814 Status: Downloaded newer image for rabbitmq:management docker.io/library/rabbitmq:management [root@192 ~]# 添加服务,设置相关属性及端口映射(包含端口 5671 5672 4369 15671 15672 25672);部署成功如下;在浏览器访问 虚拟机/服务器 IP:15672;RabbitMQ 安装成功。3. Redis 部署下载镜像 redis;[root@192 ~]# docker pull redis Using default tag: latest latest: Pulling from library/redis a2abf6c4d29d: Pull complete c7a4e4382001: Pull complete 4044b9ba67c9: Pull complete c8388a79482f: Pull complete 413c8bb60be2: Pull complete 1abfd3011519: Pull complete Digest: sha256:db485f2e245b5b3329fdc7eff4eb00f913e09d8feb9ca720788059fdc2ed8339 Status: Downloaded newer image for redis:latest docker.io/library/redis:latest [root@192 ~]# 添加服务,设置相关属性及端口映射(端口 6379); 创建成功如下;打开本地的 Redis 终端,输入 redis-cli -h 虚拟机/服务器 IP 进行连接,如下可正常运行,redis 部署成功;四、扩容与缩容扩容就是扩充容器的数量,缩容反之。在实际的运维过程中,容器需要为网站提供一个后端的支撑,当网站访问比较高的时候就需要用到更多的容器来形成容器的微服务集群,以减轻承载压力。若访问量不是那么高,则可以缩容释放出更多的空间出来。1. 扩容选择应用,添加新的服务 base-service,但不设置端口映射,创建完成后默认为一个容器;此时点击 “API” --> “WebHooks”;进入添加接收器界面,选择添加接收器,如下;选择参数之后,点击创建,此时就为服务创建了接收器(扩缩容服务);其实接收器就是配置了一个 URL,这个 URL 主要用 post 方式触发,也就是一个接口,使得某一个软件能够通过这个地址来调用 Rancher,Rancher 接收之后触发,然后进行相应的扩缩容操作。此时回到服务页面,可以看到服务的容器数量为 1;复制接收器触发地址(接口),使用本地接口测试工具调用该地址(我使用的是 ApiPost)点击发送;此时服务的容器数量便会自动增加。2. 缩容缩容操作与扩容相同,此处不再赘述。五、负载均衡器当使用扩容和缩容服务时,我们是不设置端口映射的,那么就没办法直接访问服务,为了解决此问题,Rancher 提供了负载均衡器。当想要访问没有端口映射的服务时,就需要为该服务添加负载均衡。点击 “添加服务” --> “添加负载均衡”;输入端口以及目标等信息,进行创建;此时就可以通过负载均衡器的特殊服务来访问我们的服务了。
0
0
0
浏览量2011
锅从天上来

【云原生 • Kubernetes】kubernetes 核心技术 - 集群安全机制

一、集群安全机制概述要知道,访问 Kubernetes 集群必需要进行三个步骤,即:认证 鉴权(授权) 准入控制而这个访问过程均需经过 apiserver,apiserver 主要作用就是统一协调。除此之外在访问过程中还需要证书、token、用户名/密码等等“手续”。1.认证通常的客户端身份认证有这么几种方式:HTTPS 证书认证:基于 CA 证书的认证。 HTTP Token 认证:通过 token 识别用户。 HTTP 基本认证:通过用户名+密码进行认证,安全性较低。此外,在认证过程中还有一个概念为 传输安全,意思就是对外不暴露 8080 端口,只能在内部访问。对外则统一使用端口 6443。2. 鉴权(授权)目前鉴权是基于 RBAC 进行操作的。RBAC:基于角色的访问控制。3. 准入控制这其实就是一个记录准入控制器的列表,如果该列表中包含你要请求的内容,则通过,反之则拒绝。二、RBAC 概述RBAC(基于角色的访问控制)。在 Kubernetes 集群的访问过程中,允许经过控制之后访问的某些资源,当为某一个角色设置访问内容后,将用户和角色进行绑定,那么角色可以访问的内容用户也可以访问。不仅仅是在 k8s中,其实在很多领域都在用 RBAC 机制。三、RBAC 角色绑定操作演示第一步:创建一个命名空间;#创建命名空间 kubectl create ns xiaoma第二步:在新建的命名空间下创建一个 Pod;#新建Pod kubectl run nginx --image=nginx -n xiaoma第三步:创建角色,vim 一个 yaml 文件 rbac-xiaoma.yaml,并在其中设定角色的相关属性;apiVersion: rbac.authorization.k8s.io/v1 kind: xiaoma metadata: namespace: xiaoma name: pod-reader rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "watch", "list"]代码含义:创建角色 xiaoma,该角色对 pod 拥有 get、watch、list 权限。第四步:执行文件,角色创建成功之后也可以查看角色#执行文件,即创建角色 kubectl apply -f rbac-xiaoma.yaml #查看角色 kubectl get xiaoma -n xiaoma 第五步:创建角色绑定,vim 一个 yaml 文件 rbac-xiaomabinding.yaml;apiVersion: rbac.authorization.k8s.io/v1 kind: xiaomabinding metadata: namespace: xiaomatest name: read-pods subjects: - kind: user name: majinjian apiGroup: rbac.authorization.k8s.io roleRef: kind: xiaoma name: pod-reader apiGroup: rbac.authorization.k8s.io代码含义:将用户 majinjian 与角色 xiaoma 进行绑定。第六步:执行文件并查看角色绑定用户;#执行绑定文件 kubectl apply -f rbac-xiaomabinding.yaml #查看绑定情况 kubectl get xiaoma,xiaomabinding -n xiaomatest
0
0
0
浏览量1101
锅从天上来

【云原生 • Kubernetes】配置管理 - Secret & ConfigMap

一、机密配置抽象 SecretSecret 是一种包含少量敏感信息例如密码、令牌或密钥的对象。这样的信息可能会被放在 Pod 规约中或者镜像中。使用 Secret 意味着你不需要在应用程序代码中包含机密数据。由于创建 Secret 可以独立于使用它们的 Pod,因此在创建、查看和编辑 Pod 的工作流程中暴露 Secret 及其数据的风险较小。1. 认识 SecretSecret 用于 数据加密,并将它们存储到 etcd 当中,然后让 Pod 容器以挂载 Volume 的方式进行访问。一般情况下存储的数据并不是明文,而是会将它做一些编码或者加密。例如常见的 base64 就是一种编码方式。明文:可以直接看懂的东西。如下使用 base64 编码方式输出字符串 ‘majinjian’;[root@master ~]# echo -n 'majinjian' | base64 bWFqaW5qaWFu [root@master ~]# 2. Secret 的使用(1) 创建 Secret 加密数据首先 vi secret.yaml 创建一个 Secret 加密数据(.yaml 文件),输入以下内容;apiVersion: v1 kind: Secret metadata: name: mysecret type: Opaque data: username: cm9vdA== password: cXdlcnR5dWlvcDE5OTkuLg==如下:创建成功后执行该 yaml 文件;[root@master ~]# kubectl apply -f secret.yaml 此时查看 secret,可以看到 mysecret 已创建成功;(2) 将 Secret 以变量形式挂载到 pod 容器vi secret-val.yaml 创建新的 yaml 文件 secret-val.yaml;apiVersion: v1 kind: Pod metadata: name: mypod spec: containers: - name: nginx image: nginx env: - name: SECRET_USERNAME valueFrom: secretKeyRef: name: mysecret key: username - name: SECRET_PASSWORD valueFrom: secretKeyRef: name: mysecret key: password其中:‘valueFrom’ 代表以变量形式挂载,挂载点就是我们上一步创建的 mysecret;创建成功后执行该 yaml 文件;[root@master ~]# kubectl apply -f secret-val.yaml 此时查看节点中的 pod,等待 mypod 运行(为 running 状态即可);最后进入容器查看变量是否有没有我们挂载的值;[root@master ~]# kubectl exec -it mypod bash使用 echo $变量名(如echo $SECRET_USERNAME)即可查看我们存储的变量值。二、配置抽象 ConfigMapConfigMap 是一种 API 对象,用来将非机密性的数据保存到键值对中。使用时 Pods 可以将其用作环境变量、命令行参数或者存储卷中的配置文件。 ConfigMap 会将环境配置信息和容器镜像分开来,便于应用配置的修改。但是 ConfigMap 并不提供保密或者加密功能。1. 认识 ConfigMapConfigMap 类似于 Secret,区别在于 Secret 储存加密数据,而 ConfigMap 存储的是 不加密数据,而且存储过程也与 Secret 基本相同。2. ConfigMap 的使用提示:为了便于区分操作前先删除之前创建的 secret 和容器。[root@master ~]# kubectl delete secret --all [root@master ~]# kubectl delete Pod --all(1) 创建配置文件此处要创建的是 properties 文件 vi redis.properties,输入以下内容;redis.host=127.0.0.1 redis.port=6379 redis.password=123456(2) 创建 ConfigMap[root@master ~]# kubectl create configmap redis-config --from-file=redis.properties configmap/redis-config created [root@master ~]# 此时查看 configmap(cm为它的简称),已创建成功;(3) 将 ConfigMap 以变量形式挂载到 pod 容器vi myconfig.yaml 创建配置文件 myconfig.yaml 文件,输入以下内容;apiVersion: v1 kind: ConfigMap metadata: name: myconfig namespace: default data: special.level: info special.type: hello创建成功后执行文件;[root@master ~]# kubectl apply -f myconfig.yaml configmap/myconfig created此时再次查看 ConfigMap,myconfig 也创建成功了;vi config-var.yaml 创建挂载文件 config-var.yaml 文件,输入以下内容;apiVersion: v1 kind: Pod metadata: name: mypod spec: containers: - name: busybox image: busybox command: [ "/bin/sh", "-c", "echo $(LEVEL) $(TYPE)" ] env: - name: LEVEL valueFrom: configMapKeyRef: name: myconfig key: special.level - name: TYPE valueFrom: configMapKeyRef: name: myconfig key: special.type restartPolicy: Never创建成功后执行文件;[root@master ~]# kubectl apply -f config-var.yaml pod/mypod created最受通过日志查看容器,可打印出 ‘info hello’,挂载完成;[root@master ~]# kubectl logs mypod [root@master ~]# info hello
0
0
0
浏览量2013
锅从天上来

【云服务器 ECS 实战】ECS 快照&镜像的原理及用法详解

一、ECS 快照1. 阿里云 ECS 快照概述阿里云快照服务支持所有类型的云盘,是一种低成本、便捷高效的数据备份手段,也可以用于创建镜像或容灾、分发数据副本等。对于某一个重要的磁盘数据,当我们想要给他做一个备份时,就需要用到快照。此外在进行磁盘备份之后,也有助于我们随时恢复磁盘到快照指定的状态。• ECS 增量快照机制在阿里云中使用的是 增量快照机制,所谓增量快照就是:第一次快照进行全量的数据拷贝,后续则开始进行增量拷贝,也就是说从第二次快照开始将只更新发生了变化的内容。如下图,第二次快照更新了 B1 和 C1,A 和 D 都是链接的第一次快照中的内容,第三次快照更新了 B2,C1 是链接的第二次快照的内容,A 和 D 链接的还是第一次快照的内容。使用增量快照机制的好处在于第一可以大大提高执行快照的效率(只有第一次快照所需时间会比较长),其次是占用磁盘容量小,节省存储成本。2. 快照服务的开通与使用• 开通快照与 OSS 资源包的购买快照服务的使用需要先开通,开通不会收费,但是后续使用使用是会收费的,按照时长与存储量收费,所以定期清理不需要的快照是非常有必要的。如下:点击“开通快照服务”后,第二步进行 OSS 资源包的购买;OSS 资源包的选型这里不再多说,规格方面通常情况下 40G 足矣;购买资源包之后,我们还需要回到控制台,点击“查看资源包”,然后开通该资源包;资源包开通后如下,此时就可以在我们的实例上使用快照服务了;• 手动快照快照服务的使用分为 手动快照 和 自动快照 两种。 手动快照顾名思义每一次都需要我们手动去为实例创建快照,回到控制台,选择“实例”,在实例的操作属性中有“创建实例快照”选项,然后输入相关参数创建即可;• 自动快照是否使用以及什么时候使用自动快照应根据我们的业务类型与应用场景来定,如果业务和应用通常是在晚上的高峰期执行,那么自动快照设置在白天比较好。此外过于频繁的更新快照,也可能会造成数据丢失,性能下降等问题。所以使用自动快照必须是在能够清晰定位自己的业务类型和应用场景的前提下。回到控制台,选择左侧菜单的“快照”,可以看到有一个“自动快照策略”,在此处进行自动快照的创建;策略各参数如下:在使用快照的过程中,可随时使用命令查看磁盘容量的使用情况。df -hTips:使用快照服务时应注意以下事项:避开核心应用交叉影响;执行自动快照之前先清理不必要的数据;预估系统的增长量;要有合理的备份时间间隔,避免备份耗时大于自动备份时间间隔(在阿里云中,如果第一次备份未完 成,第二次是不会被允许的);先购买存储包再使用快照服务;在创建快照的过程中,不要对 ECS 执行重启操作;二、ECS 镜像1. 阿里云 ECS 镜像概述镜像 类似于模板,镜像中包含着操作系统、预装软件甚至是代码应用等。我们可以使用这个模板快速生成一个新的 ECS 实例,这个模板可以是自定义的,也可以拿来别人的。这样我们就不用重复多次的去搭建某个环境或者是部署某个应用了。通过镜像一键部署,自行配置环境、安装软件,可解决一些繁琐耗时的任务。在阿里云中一共提供了 5 种镜像,即 自定义镜像、公共镜像、共享镜像、镜像市场、社区镜像;我们购买并配置的服务器的默认实例就是阿里云官方提供的公共镜像。2. 自定义镜像的创建与使用回到阿里云控制台,进入左侧菜单栏的“镜像”,即可进行镜像的创建、更新、复制、导入等操作;• 导入镜像对于自定义镜像,我们可以有几种方式来生成。导入镜像需要我们自己完成镜像并上传,比如说本地虚拟机的磁盘文件,我们可将其上传至阿里云后台,然后导入,这就是一个自定义镜像。具体操作是,首先进入对象存储 OSS 控制台,创建并选择一个 bucket,然后选择本地已经做好的镜像进行上传;上传镜像之后就可以在 OSS 控制台获取到镜像文件的 URL ,复制 URL,回到控制台,选择“导入镜像”,此时需要用到 URL 进行镜像的导入;• 自定义镜像回到实例,没有实例可使用公共镜像先创建实例;我这里以云服务器的默认实例进行演示,该实例已经配置好了相关环境且部署了相关服务,我们可以把此实例直接打成一个镜像。选择“更多”属性,可以看到对于镜像的相关操作;镜像的创建很简单,填写相关属性创建即可;镜像创建成功之后,回到左侧菜单栏的“镜像”,就可以看到我们刚刚创建的自定义镜像。可以对该镜像进行共享、发布到社区或者使用该镜像生成实例等一系列操作。要注意,使用自定义镜像生成实例时必须选择同一个区域(比如“华北2”等),否则是无法使用的。
0
0
0
浏览量2010

履历