侧边栏壁纸
博主头像
Blog博主等级

行动起来,活在当下

  • 累计撰写 211 篇文章
  • 累计创建 94 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Kubernetes修炼手册阅读笔记

应用(pod)创建过程:

(http、restful api)api-server <-----(listen) ---kubelet controller ----->cri ----->Deployment controller--->pods

kubectl --http post---> .yaml ->control-plane

pod ---> 1个或多个容器。同一个pod中多个容器之间的共享的。

svc 的作用:

Deployment 扩缩容会使pod ip发生变化-->service 分配固定IP保证服务的网络稳定。

微服务一个容器实现一个需求。

/ web

pod ---》共享同一个卷

\ 文件同步

pod部署过程:

部署清单(.yaml格式) -----post--》 API server (contorl plane检查yaml格式)->记录到集群存储-》调度集群节点部署。

pod中所有容器都共享相同的网络、存储空间。

每个容器都有其自己的端口,同一个 Pod中的容器不能使用同一个端口。

deployment 使用replica set 来自愈和扩缩容

deployment --管理> replicaset --管理-> pod

声明式:整体(推荐使用)

命令式:局部拼接

replicaset 名称是deployment 的名称与一个hash值的拼接。

hash 值是对 YAML 清单文件中 Pod 模板部分(spec.template 下的所有内容)的hash。

kubectl get rs -owide

kubectl get deploy -owide

svc:

创建固定IP或域名,无论集群内部pod如何变化,不会影响从外部的访问。

svc支持的四种模式:

ClusterIP:(只可以集群内部访问)

kubectl expose deploy whoami --port=80

NodePort:(将集群中pod端口暴露到外部)

kubectl expose deploy whoami --type=NodePort --port 80

LoadBalancer:(将集群中pod端口暴露到互联网,常用于云。像是ClusterIP和NodePort 模式的结合体)。

kubectl expose deploy whoami --type=LoadBalancer --port=80 --external-ip <PUBLIC_IP>

ExternalName:能够将流量路由至 Kubernetes 集群之外的系统中去(所有其他类 型的 Service 都是在集群内部进行流量的路由)。

查看扩缩容状态:

kubectl rollout status deployment hello-deploy

扩缩容时添加了--record 参数会记录版本历史记录。

kubectl rollout history deployment hello-deploy

版本回退到v1

kubectl rollout undo deployment hello-deploy --to-revision=1

service 利用label来动态选择将流量转发至哪些pod。label是service和pod之间的桥梁。

kubectl get po -l app=whoami

例如:

servcie中有两个标签:

app = nginx

run = nginx

pod中只有一个标签:

app = nginx

那么service 的流量不会经过该pod

pod中有多个标签

app = nginx

run = nginx

ver = v1

sta = running

其中标签app = nginx、run = nginx和service中标签匹配。service会将流量转发到该pod。

svc yml文件分析

apiVersion: v1
kind: Service
metadata:
 name: hello-svc
 labels:
   app: hello-world
spec:
 type: NodePort
 ports:
 - port: 8080
   nodePort: 30001
   targetPort: 8080
   protocol: TCP
 selector:
   app: hello-world

从集群外访问pod内部应用流量走势:

外网流量-》nodeport(30001)->targetport(8080)->port(8080)

流量先到svc的NodePort 端口,再到endpoints 端口,最后转到pod 应用内部端口。

查看svc

[root@k3s-master yml]# kubectl describe svc whoami 
Name:                     whoami
Namespace:                default
Labels:                   app=whoami
Annotations:              <none>
Selector:                 app=whoami
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.43.128.157
IPs:                      10.43.128.157
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
NodePort:                 <unset>  30194/TCP
Endpoints:                10.42.0.66:80,10.42.1.41:80,10.42.1.66:80 + 2 more...
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

查看endpoints

[root@k3s-master yml]# kubectl describe  endpoints whoami 
Name:         whoami
Namespace:    default
Labels:       app=whoami
Annotations:  endpoints.kubernetes.io/last-change-trigger-time: 2024-05-21T08:59:34Z
Subsets:
  Addresses:          10.42.0.66,10.42.1.41,10.42.1.66,10.42.2.77,10.42.2.78
  NotReadyAddresses:  <none>
  Ports:
    Name     Port  Protocol
    ----     ----  --------
    <unset>  80    TCP

Events:  <none>

集群中每一个节点都运行一个kube-proxy,它实现监视Api-server上新创建的Service和Endpoint的控制器。当它有新发现时,就会创建一条本地的IPVS规则该规则告诉主机节点拦截发往Service的ClusterIP的流量,并发送至具体的Pod。

下图表示从一个应用(pod)访问另一个应用(pod)的(流量传递)过程。

pod之间流量传递过程-min.webp

其中捕获这一环节就是由kube-proxy完成的。

相同ns之间的pod访问:

curl pod名称:应用端口

如:

curl ent:8080

不同ns之间的pod访问:

如:

ns: dev

pod名称 : ent

ns: prod

pod名称 : ent

在dev pod中访问prod中的pod ent

curl  prod.svc.cluster.local:8080

说明短名称会被解析到自身所在的命名空间,而跨命名空间的连接则需要使用FQDN。

进入dev pod 内部查看域名解析发现:

cat /etc/resolv.conf

root@jump:/# cat /etc/resolv.conf 

search dev.svc.cluster.local svc.cluster.local cluster.local

nameserver 10.43.0.10

options ndots:5

本地域名是:dev.svc.cluster.local

对应的dns ip是:10.43.0.10

正好是coredns 的内部IP。说明到达pod的流量都会转给kube-dns。

[root@k3s-master yml]# kubectl get svc -n kube-system -l k8s-app=kube-dns

NAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE

kube-dns   ClusterIP   10.43.0.10   <none>        53/UDP,53/TCP,9153/TCP   8d

存储:

pvc:像许可证,赋予pod访问pv的权限

pv : k8s中存储

sc:动态分配

pvc三种模式:

ReadWriteOnce(RWO):

限制一个PV只能以读写方式被挂载或绑定到一个PVC。尝试绑定多个会失败。

ReadWriteMany(RWM)

可以绑定多个。通常只支持NFS。块存储只支持RWO

ReadOnlyMany(ROM)

允许PV以只读方式绑定到多个PVC。

需要强调几点。首先,一个 PV 只能设置一种模式:不能在与一个 PVC 以 ROM 模式绑定的同时再与另一个 PVC 以 RWM 模式绑定。其次,Pod 不能直接与 PV 对接,而是必须通过 PVC 与某个 PV 绑定。

StorageClass 使我们无须手动创建 PV,只需要创建一个StorageClass 对象,然后使用一个插件将其与某个具体的存储后端联系起来。

pv 与pvc 绑定如下:

pv和pvc绑定-min.webp

两种命令式创建comfigmap的方式

1. 基于字面值(--from-literal)

kubectl create configmap testmap1 --from-literal shortname=msb.com --from-literal longname=magicsandbox.com

2. 基于已有的文件(--from-file)

假设文件cmfile.txt 内容为:
Magic Sandbox, hands-on learning that blurs the lines between training and the real world. 

创建cm

kubectl create configmap testmap2 --from-file cmfile.txt 

查看cm 详情:

kubectl describe cm testmap1

声明式创建cm 的方式:

multimap.yml

kind: ConfigMap
apiVersion: v1
metadata: 
  name: multimap
data: 
  given: Nigel
  family: Poulton

singlemap.yml

kind: ConfigMap
apiVersion: v1
metadata:
  name: test-config
data:
  test.conf: |
    env = plex-test
    endpoint = 0.0.0.0:31001
    char = utf8
    vault = PLEX/test
    log-size = 512M

kubectl apply -f multimap.yml

kubectl apply -f singlemap.yml

使用管道符"|" 将管道符后面的所有内容整体看作value。key为: test.conf

key和value 统一称作entity。

所有的键值对都在data字段中。

ConfigMap对象没有状态(期望状态和当前状态)的概念。因此它没有spec和status部分,取而代之的是data。

三种方式将cm数据注入pod和容器

1.作为环境变量

先创建cm,然后将entity映射到位于pod template 的 container 部分环境变量中。当容器启动时,环境变量会以Linux或windows环境变量形式出现在容器中。

图解如下:

cm与环境变量-min.webp

comfigmap文件 multimap.yml

kind: ConfigMap
apiVersion: v1
metadata: 
  name: multimap
data: 
  given: Nigel
  family: Poulton

pod 文件envPod.yml

apiVersion: v1
kind: Pod
metadata:
  labels:
    chapter: configmaps
  name: envpod
spec:
  containers:
    - name: ctr1
      image: busybox
      command: ["sleep"]
      args: ["infinity"]
      env:
        - name: FIRSTNAME
          valueFrom:
            configMapKeyRef:
              name: multimap
              key: given
        - name: LASTNAME
          valueFrom:
            configMapKeyRef:
              name: multimap
              key: family

kubectl apply -f multimap.yml

kubectl apply -f envPod.yml

[root@k3s-master yml]# kubectl exec envpod -- env | grep NAME 
HOSTNAME=envpod
LASTNAME=Poulton
FIRSTNAME=Nigel

将cm作为环境变量来使用有缺点,环境变量是静态的。即使更改了cm中的内容,容器中的环境变量也不会发生变化。

2.作为容器启动参数

startuppod.yml

apiVersion: v1
kind: Pod
metadata:
  name: startup-pod
  labels:
    chapter: configmaps
spec:
  restartPolicy: OnFailure
  containers:
    - name: args1
      image: busybox
      command: [ "/bin/sh", "-c", "echo First name $(FIRSTNAME) last name $(LASTNAME)", "wait" ]
      env:
        - name: FIRSTNAME
          valueFrom:
            configMapKeyRef:
              name: multimap
              key: given
        - name: LASTNAME
          valueFrom:
            configMapKeyRef:
              name: multimap
              key: family

还是先创建cm(本例中使用上例的multimap作为cm),然后Pod模板(template,YAML文件中定义Pod及其容器的部分)定义了一个名为 args1的容器。容器基于busybox镜像,并且执行/bin/sh命令。

FIRSTNAME 基于cm multimap 的given entry

LASTNAME 基于cm multimap 的family entry

图解如下:

cm与命令-min.webp

查看容器日志:

[root@k3s-master yml]# kubectl logs startup-pod -c args1 
First name Nigel last name Poulton

查看容器环境变量

[root@k3s-master yml]# kubectl describe  po startup-pod | grep -i env -A 2
    Environment:
      FIRSTNAME:  <set to the key 'given' of config map 'multimap'>   Optional: false
      LASTNAME:   <set to the key 'family' of config map 'multimap'>  Optional: false

在容器的启动命令中使用ConfigMap,也会遇到和作为环境变量使用的时候同样的限制--对ConfigMap的更新不会同步到已运行的容器中。

3.作为某个卷上的文件

步骤:

先创建cm,在pod模板中创建一个c'm卷,将cm卷挂载到容器中。

cm中的entry会分别作为单独的文件出现在容器中。

图解如下:

cm与卷-min.webp

还是会得到cm multimap中的两个值:

given = Nigel

family = Poulton

创建了一个名为:cmvol 的pod

spec.volumes创建了一个基于ConfigMap multimap的名为volmap的卷。

spec.containers.volumeMounts 将volmap卷挂载到/etc/name。

cmpod.yml

apiVersion: v1
kind: Pod
metadata:
  name: cmvol
spec:
  volumes:
    - name: volmap
      configMap:
        name: multimap
  containers:
    - name: ctr
      image: nginx
      volumeMounts:
        - name: volmap
          mountPath: /etc/name

在spec.containers中将volmap卷挂载到了容器的/etc/name。也就是说在容 器中,两个文件的路径如下。

/etc/name/given。

/etc/name/family。

$ kubectl apply -f cmpod.yml 
Pod/cmvol created 
$ kubectl exec cmvol -- ls /etc/name 
family 
given 

cm是k8s提供的用于将应用和配置进行解耦的配置。它可用于保存应用的配置参数,甚至完整的配置文件,但不应被保存敏感数据。

cm是在容器运行时注入的,它可以通过环境变量、容器启动命令和卷三种途径注入容器卷的方式是最灵活的,容器能够以文件形式获取配置,同时将对cm更新同步到已运行的容器中。

2

评论区