Kubernetes 学习整理(三)

k8s

kubelet (Kubernetes node agent): 是运行在每个节点上的代理,负责管理该节点上的容器, 它从 Kubernetes Master 接收 Pod 的描述,并确保节点上运行的容器与描述一致。不能跨节点。
kubelet 的主要作用是保证节点上的容器按照期望的状态运行。它监控容器的健康状态,执行生命周期操作,并报告状态给 Kubernetes Master。

kubectl(kubernetes 集群维护检查): 部署应用程序、创建和管理 Kubernetes 资源,以及监控集群中的各种状态

kube-apiserver
拉取 kube-apiserver 镜像,如果没有显示,则启动一个 goroutine 来等待 etcd,然后在 /var/lib/rancher/rke2/agent/pod-manifests/ 中写入静态 pod 定义。

ll /var/lib/rancher/rke2/agent/pod-manifests/
total 32
-rw-r--r-- 1 root root 3282 Jan 17 22:52 etcd.yaml
# 是分布式键值存储系统,用于存储 Kubernetes 集群的配置信息、状态和元数据。它是集群的数据存储后端。
# 需要足够的权限以接受和处理来自 kube-apiserver 的写入和读取请求。存储和提供集群的配置信息,保持集群状态的一致性。
-rw-r--r-- 1 root root 9704 Jan 17 22:55 kube-apiserver.yaml
# 负责提供集群的 API 接口。它接收来自各种客户端(如 kubectl、Controller Manager、Scheduler 等)的请求,并将这些请求转换成对集群状态的操作。支持资源的创建、更新、删除等操作,同时执行身份验证和授权。
-rw-r--r-- 1 root root 5468 Jan 17 22:55 kube-controller-manager.yaml
# 包含多个控制器,每个控制器负责监控集群中的不同资源类型。控制器的任务包括确保实际状态与期望状态一致,处理故障恢复等。
-rw-r--r-- 1 root root 2444 Jan 17 22:55 kube-proxy.yaml
# 运行在每个节点上,其作用范围限定在单个节点上, 主要涉及网络规则的设置,通常需要足够的权限以配置节点上的网络规则。
-rw-r--r-- 1 root root 3895 Jan 17 23:16 kube-scheduler.yaml
# 负责将新创建的 Pod 调度到集群中的节点上。它考虑节点资源、亲和性、亲和性规则等因素来选择最合适的节点,并更新调度的相关状态。
drwxr-xr-x 1 root root  138 Jan 17 23:16 scheduler

ll /var/lib/rancher/rke2/agent/pod-manifests/scheduler/
total 20
-rw-r--r-- 1 root root  433 Jan 17 23:16 config-19.yaml
-rw-r--r-- 1 root root  433 Jan 17 23:16 config-23.yaml
-rw-r--r-- 1 root root  350 Jan 17 23:16 config.yaml
-rw-r--r-- 1 root root 2729 Jan 17 23:16 kube-scheduler.yaml
-rw-r--r-- 1 root root  266 Jan 17 23:16 policy.yaml

Etcd 和 Kubernetes Control Plane 组件在 kube-system 命名空间中作为静态 Pod 运行。
可以使用 kubectl 访问每个 Kubernetes Pod 的日志:

/var/lib/rancher/rke2/bin/kubectl --kubeconfig /etc/rancher/rke2/rke2.yaml logs -n kube-system -l component=kube-apiserver

使用 kubectl 从外部访问集群
将 /etc/rancher/rke2/rke2.yaml 复制到位于集群外部的主机上的 ~/.kube/config。然后将 127.0.0.1 替换为 RKE2 server 的 IP 或主机名。现在,你可以使用 kubectl 来管理 RKE2 集群。

/var/lib/rancher/rke2 是 RKE2 的默认数据目录, 快照是默认启动的

# 手动执行快照: rke2 etcd-snapshot save --name pre-upgrade-snapshot
ll /var/lib/rancher/rke2/server/db/snapshots
total 222768
-rw------- 1 root root 38015008 Jan 19 12:00 etcd-snapshot-ali1-atlantic-host-1705694403
-rw------- 1 root root 38015008 Jan 20 00:00 etcd-snapshot-ali1-atlantic-host-1705737602
-rw------- 1 root root 38015008 Jan 20 12:00 etcd-snapshot-ali1-atlantic-host-1705780802
-rw------- 1 root root 38015008 Jan 21 00:00 etcd-snapshot-ali1-atlantic-host-1705824001
-rw------- 1 root root 38015008 Jan 21 12:00 etcd-snapshot-ali1-atlantic-host-1705867202
-rw------- 1 root root 38015008 Jan 21 19:21 pre-upgrade-snapshot-ali1-atlantic-host-1705893675

Helm 是 Kubernetes 的包管理工具。Helm Chart 为 Kubernetes YAML 清单文件提供了模板语法。通过 Helm,用户可以创建可配置的 deployment,而不仅仅只能使用静态文件。

日志:
journalctl -u rke2-server
journalctl -u rke2-agent
/var/log/syslog
/var/lib/rancher/rke2/agent/containerd/containerd.log
/var/lib/rancher/rke2/agent/logs/kubelet.log

每个容器的日志都写入 /var/log/pods,你也可以使用 crictl 访问:

export CONTAINER_RUNTIME_ENDPOINT=unix:///run/k3s/containerd/containerd.sock
# 列出运行的容器
/var/lib/rancher/rke2/bin/crictl ps
# 通过容器 ID 获取容器日志
/var/lib/rancher/rke2/bin/crictl logs <container_id>

rke2-server 主要运行 etcd(用于存储集群状态)、kube-apiserver(提供 Kubernetes API)、kube-controller-manager(运行控制器)、kube-scheduler(调度器)等控制平面组件。。

rke2-agent 运行 Pod 和容器,负责执行实际的应用程序工作负载, 将节点注册到 etcd 中,以及与 rke2-server 通信以保持集群状态一致。

  1. Create a Kubernetes cluster

  2. Deploy an app

  3. Explore your app
    kubectl get pods 命令检查您的应用程序的 Pod 是否已成功启
    kubectl logs 命令查看应用程序 Pod 的日志,以了解应用程序的运行状况和可能的错误。
    kubectl get services 命令检查服务的状态。

  4. Expose your app publicly:通过执行 "Expose your app publicly" 步骤,您可以确保应用程序可以从集群外部访问,提供给外部用户或其他系统使用。
    kubectl expose 命令或通过定义一个 Service YAML 文件来创建一个 Kubernetes Service
    进一步公开应用程序,使其可以通过集群节点的公共 IP 地址和一个公共端口访问。这通常使用 Service 类型为 LoadBalancer 或 NodePort 来完成。
    kubectl get services 命令检查新创建的 Service 的外部 IP 地址和端口。
    使用提供的 IP 地址和端口访问您的应用程序。这可以通过浏览器、curl 或其他工具来完成。

  5. Scale up your app 第3 4 步骤分别是做什么

Deploy an app

1. kubectl create deployment kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1

2. kubectl get deployments

View the app

# open a second terminal window to run the proxy:
1. kubectl proxy

# query the version directly through the API using the curl command:
2. curl http://localhost:8001/version
{
  "major": "1",
  "minor": "27",
  "gitVersion": "v1.27.6+rke2r1",
  "gitCommit": "741c8db18a52787d734cbe4795f0b4ad860906d6",
  "gitTreeState": "clean",
  "buildDate": "2023-09-13T19:23:53Z",
  "goVersion": "go1.20.8 X:boringcrypto",
  "compiler": "gc",
  "platform": "linux/amd64"


# First we need to get the Pod name, and we'll store in the environment variable POD_NAME:

3. export POD_NAME=$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')
4. echo Name of the Pod: $POD_NAME
5. curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME/
6. curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME:8080/proxy/

# Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-855d5cc575-v22dh | v=1

Explore the APP

kubectl get - list resources
kubectl describe - show detailed information about a resource
kubectl logs - print the logs from a container in a pod
kubectl exec - execute a command on a container in a pod

kubectl logs "$POD_NAME"
kubectl exec "$POD_NAME" -- env

在container 内部执行

# 进入container内部的bash
kubectl exec -ti $POD_NAME -- bash
root@kubernetes-bootcamp-855d5cc575-v22dh:/#

# 在container内部执行cli
root@kubernetes-bootcamp-855d5cc575-v22dh:/# cat server.js
var http = require('http');
var requests=0;
var podname= process.env.HOSTNAME;
var startTime;
var host;

# 在container内部 访问8080
root@kubernetes-bootcamp-855d5cc575-v22dh:/# curl http://localhost:8080
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-855d5cc575-v22dh | v=1

exit

Expose the APP

Replica set

监控pods的运行状态,确保实际运行的和期望的一致。
observed state vs desired state

ReplicaSet:
Pod 副本管理: ReplicaSet 负责确保在集群中始终运行指定数量的 Pod 副本。它使用 Label Selector 来标识要监控和维护的 Pod。

Self-Healing: 如果实际运行的 Pod 数量和 ReplicaSet 期望的数量不一致,ReplicaSet 会采取措施来修复这个差异。例如,如果有更多的 Pod 实例运行,它可能会终止一些多余的实例。如果缺少实例,它可能会创建新的 Pod 来满足期望的数量。

Service:
服务访问与负载均衡: Service 负责提供一个稳定的入口点,使其他应用程序或服务能够访问一组 Pod。Service 通常与 Label Selector 结合使用,以将请求路由到属于特定组的 Pod。

Traffic Balancing: Service 提供负载均衡功能,以确保请求被分发到属于服务的多个 Pod 实例。这有助于实现高可用性和水平扩展。

关系:
协同工作: ReplicaSet 通常与 Deployment 一起使用,Deployment 提供了对 ReplicaSet 的声明性定义,允许轻松地进行滚动更新和版本控制。Deployment 控制 ReplicaSet 的创建和更新。

Traffic Balancing: Service 与 ReplicaSet 一起使用,Service 可以路由流量到由 ReplicaSet 管理的多个 Pod。这帮助实现服务的可扩展性和高可用性。

Lables (key/value pairs), selectors

  1. A Service is defined using YAML or JSON, which defines a logical set of Pods and a policy by which to access them.
  2. The set of Pods targeted by a Service is usually determined by a label selector.
  3. Services match a set of Pods using labels and selectors.
  4. Lable: 为对象添加的元数据; Selector: 是一种选择机制,根据指定label选择一组对象。

具体流程如下:

**Deployment: **创建一个 Deployment 对象,该对象定义了您要运行的应用程序(app)的副本数量、Pod 模板等信息。Deployment 会确保指定数量的 Pod 副本在集群中运行,并在需要时进行扩展或缩减。

示例 Deployment YAML:

Copy code
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-app-container
        image: my-app-image:latest

**Service: **为了使其他应用程序或服务能够访问您的应用程序,您创建一个 Service 对象。Service 为一组符合特定标签条件的 Pod 提供了一个虚拟 IP 地址(Cluster IP),并可以选择通过负载均衡提供公共 IP 地址和端口。

示例 Service YAML:

Copy code
apiVersion: v1
kind: Service
metadata:
  name: my-app-service
spec:
  selector:
    app: my-app
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

通过这样的设置,其他应用程序或服务可以通过 my-app-service 访问您的应用程序,而无需直接关心底层 Pod 的标识。Service 将负责将流量分发到后端运行的多个 Pod,并提供负载均衡的功能,确保应用程序的高可用性和扩展性。

Services allow your applications to receive traffic. Services can be exposed in different ways by specifying a type in the spec of the Service:

ClusterIP (default) - Exposes the Service on an internal IP in the cluster. This type makes the Service only reachable from within the cluster.

NodePort - Exposes the Service on the same port of each selected Node in the cluster using NAT. Makes a Service accessible from outside the cluster using <NodeIP>:<NodePort>. Superset of ClusterIP.

LoadBalancer - Creates an external load balancer in the current cloud (if supported) and assigns a fixed, external IP to the Service. Superset of NodePort.

ExternalName - Maps the Service to the contents of the externalName field (e.g. foo.bar.example.com), by returning a CNAME record with its value. No proxying of any kind is set up. This type requires v1.7 or higher of kube-dns, or CoreDNS version 0.0.8 or higher.

Create a service

step1: 查看现有pod 和现有service

 kubectl get pods
NAME                                   READY   STATUS    RESTARTS   AGE
kubernetes-bootcamp-855d5cc575-v22dh   1/1     Running   0          56m

kubectl get services
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.43.0.1    <none>        443/TCP   4d

step 2: expose service

kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080
service/kubernetes-bootcamp exposed

kubectl get services
NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes            ClusterIP   10.43.0.1       <none>        443/TCP          4d
kubernetes-bootcamp   NodePort    10.43.186.203   <none>        8080:31816/TCP   4s

step 3: 查看 service 详细信息

kubectl describe services/kubernetes-bootcamp
Name:                     kubernetes-bootcamp
Namespace:                default
Labels:                   app=kubernetes-bootcamp
Annotations:              <none>
Selector:                 app=kubernetes-bootcamp
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.43.186.203
IPs:                      10.43.186.203
Port:                     <unset>  8080/TCP
TargetPort:               8080/TCP
NodePort:                 <unset>  31816/TCP
Endpoints:                10.42.0.22:8080
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

step 4: 查看pod详细信息

 kubectl get pods kubernetes-bootcamp-855d5cc575-v22dh --show-labels
NAME                                   READY   STATUS    RESTARTS   AGE   LABELS
kubernetes-bootcamp-855d5cc575-v22dh   1/1     Running   0          60m   app=kubernetes-bootcamp,pod-template-hash=855d5cc575

kubectl describe pod kubernetes-bootcamp-855d5cc575-v22dh
Name:                 kubernetes-bootcamp-855d5cc575-v22dh
Namespace:            default
Priority:             500000
Priority Class Name:  cmo-medium-priority
Service Account:      default
Node:                 ali1-atlantic-node-3/10.224.35.209
Start Time:           Sun, 21 Jan 2024 22:27:58 -0800
Labels:               app=kubernetes-bootcamp

step 5: 拿到 service所在node的port

export NODE_PORT="$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}')"

echo "NODE_PORT=$NODE_PORT"

# NODE_PORT=31816

step 6: 访问app, 要用它的node 和 port, 因为type是NodePort,意思是所有node上的这个port都可以访问

export NODE_IP="$(kubectl get nodes -o jsonpath='{.items[0].status.addresses[?(@.type=="InternalIP")].address}')"

echo $NODE_IP
# 10.224.35.217

curl http://"10.224.35.209:$NODE_PORT"
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-855d5cc575-v22dh | v=1

curl http://"10.224.35.210:$NODE_PORT"
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-855d5cc575-v22dh | v=1

Using labels

  1. 查看 deploy
# 查看 deploy
kubectl describe deployment

Name:                   kubernetes-bootcamp
Namespace:              default
CreationTimestamp:      Sun, 21 Jan 2024 22:27:58 -0800
Labels:                 app=kubernetes-bootcamp
Annotations:            deployment.kubernetes.io/revision: 1
Selector:               app=kubernetes-bootcamp
Replicas:               1 desired | 1 updated | 1 total | 1 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  app=kubernetes-bootcamp
  Containers:
   kubernetes-bootcamp:
    Image:        gcr.io/google-samples/kubernetes-bootcamp:v1
    Port:         <none>
    Host Port:    <none>
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   kubernetes-bootcamp-855d5cc575 (1/1 replicas created)
Events:          <none>

  1. 用label来查询相关的pod
# 用label来查询相关的po
kubectl get pods -l app=kubernetes-bootcamp

NAME                                   READY   STATUS    RESTARTS   AGE
kubernetes-bootcamp-855d5cc575-v22dh   1/1     Running   0          86m
  1. 用label 来查询相关的service
# 用label 来查询相关的service
kubectl get services -l app=kubernetes-bootcamp

NAME                  TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes-bootcamp   NodePort   10.43.186.203   <none>        8080:31816/TCP   30m
  1. 提取pod name
export POD_NAME="$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')"
echo "Name of the Pod: $POD_NAME"
# Name of the Pod: kubernetes-bootcamp-855d5cc575-v22dh
  1. 给pod 增加新label
kubectl label pods "$POD_NAME" version=v1
# pod/kubernetes-bootcamp-855d5cc575-v22dh labeled

  1. 查看已经有新label啦
kubectl describe pods "$POD_NAME"
Name:                 kubernetes-bootcamp-855d5cc575-v22dh
Namespace:            default
Priority:             500000
Priority Class Name:  cmo-medium-priority
Service Account:      default
Node:                 ali1-atlantic-node-3/10.224.35.209
Start Time:           Sun, 21 Jan 2024 22:27:58 -0800
Labels:               app=kubernetes-bootcamp
                      pod-template-hash=855d5cc575
                      version=v1
  1. 用新label 来查询相关的service
# 用新label 来查询相关的service
kubectl get pods -l version=v1
NAME                                   READY   STATUS    RESTARTS   AGE
kubernetes-bootcamp-855d5cc575-v22dh   1/1     Running   0          90m

# 另一个label也可以
kubectl get services -l app=kubernetes-bootcamp
NAME                  TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes-bootcamp   NodePort   10.43.186.203   <none>        8080:31816/TCP   33m

  1. 用label delete service
kubectl get service
NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes            ClusterIP   10.43.0.1       <none>        443/TCP          4d1h
kubernetes-bootcamp   NodePort    10.43.186.203   <none>        8080:31816/TCP   35m
kubectl delete service -l app=kubernetes-bootcamp
service "kubernetes-bootcamp" deleted

kubectl get service
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.43.0.1    <none>        443/TCP   4d1h

This proves that the application is not reachable anymore from outside of the cluster. You can confirm that the app is still running with a curl from inside the pod:

  1. 再次访问这个service,已经访问不到了
echo $NODE_IP
10.224.35.217
echo $NODE_PORT
31816
curl http://"$NODE_IP:$NODE_PORT"
curl: (7) Failed to connect to 10.224.35.217 port 31816 after 0 ms: Couldn't connect to server
  1. 但是cluster内部还是能访问的:
kubectl exec -ti $POD_NAME -- curl http://localhost:8080
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-855d5cc575-v22dh | v=1
posted @ 2024-01-24 15:17  vivi~  阅读(11)  评论(0编辑  收藏  举报