Kubernetes简介

Kubernetes 是 Google 团队发起的开源项目,它的目标是管理跨多个主机的容器,提供基本的部署,维护以及运用伸缩,主要实现语言为Go语言。Kubernetes 特性有:

  • 易学:轻量级,简单,容易理解
  • 便携:支持公有云,私有云,混合云,以及多种云平台
  • 可拓展:模块化,可插拔,支持钩子,可任意组合
  • 自修复:自动重调度,自动重启,自动复制

Kubernetes 构建于 Google 数十年经验,一大半来源于 Google 生产环境规模的经验。结合了社区最佳的想法和实践。在分布式系统中,部署,调度,伸缩一直是最为重要的也最为基础的功能。Kubernets 就是希望解决这一序列问题的。Kubernets 目前在GitHub进行维护。

目前,Kubenetes 支持在多种环境下的安装,包括本地主机(Fedora)、云服务(Google GAE、AWS 等)。然而最快速体验 Kubernetes 的方式显然是本地通过 Docker 的方式来启动相关进程。

下图展示了在单节点使用 Docker 快速部署一套 Kubernetes 的拓扑。

image-20230401171302899

Minikube

Minikube是一种工具,可以在本地轻松运行Kubernetes。 Minikube在笔记本电脑的VM中运行单节点Kubernetes集群,供那些希望尝试Kubernetes或者日常开发的用户使用,本节实验将基于Minikube来完成。

Minikube支持以下特性:

  • DNS
  • NodePorts
  • ConfigMaps and Secrets
  • Dashboards
  • Container Runtime: Docker, rkt, CRI-O and containerd
  • Enabling CNI (Container Network Interface)
  • Ingress

实验1. Minikube基本操作

1.1. 启动 Minikube

执行以下命令启动docker及minikube

1
# start.sh

image-20230401171309822

1.2. 查看集群状态

可以使用kubectl CLI与集群进行交互。这是用于管理Kubernetes和在群集上运行的应用程序的主要方法。

可以通过以下方式发现群集及其运行状况的详细信息:

1
2
3
4
# kubectl cluster-info

Kubernetes master is running at https://127.0.0.1:8443
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

image-20230401171323911

1.3. 查看集群节点

使用 kubectl get nodes 列出节点:

1
2
3
# kubectl get nodes
NAME STATUS ROLES AGE VERSION
30b561aec9a2 Ready <none> 52s v1.8.0

image-20230401171331231

如果节点标记为NotReady,则它仍在启动组件。此命令显示可用于托管应用程序的所有节点。现在我们只有一个节点,我们可以看到它的状态已准备好(它已准备好接受部署的应用程序)。

实验2. 通过 kubectl 部署容器

其群启动完成以后,可以使用 kubectl 进行部署容器操作

2.1 启动容器

执行以下命令启动一个nginx服务:

1
# kubectl run first-deployment --image=nginx:alpine --port=80

image-20230401171336641

2.2 查看Pod状态

可以通过以下方式查看Pod状态:

1
2
3
4
# kubectl get pod

NAME READY STATUS RESTARTS AGE
first-deployment-84d55ddb97-pt6ws 1/1 Running 0 12s

image-20230401171355912

当pod状态为 Running 时,说明 pod 启动完成,容器正在运行

2.3 暴漏服务端口

容器运行后,可以根据需要通过不同的网络选项进行暴露。 一种可能的解决方案是NodePort,它为容器提供动态端口:

1
# kubectl expose deployment first-deployment --port=80 --type=NodePort

如果节点标记为NotReady,则它仍在启动组件。此命令显示可用于托管应用程序的所有节点。现在我们只有一个节点,我们可以看到它的状态已准备好(它已准备好接受部署的应用程序)。

2.4 查找已分配的端口并执行HTTP请求

以下命令查找已分配的端口并执行HTTP请求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# export PORT=$(kubectl get svc first-deployment -o go-template='{{range.spec.ports}}{{if .nodePort}}{{.nodePort}}{{"\n"}}{{end}}{{end}}')
# echo "$PORT"
# curl localhost:$PORT

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
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>

image-20230401171407329

2.5 删除 nginx服务

1
2
# kubectl delete deploy/first-deployment
deployment "first-deployment" deleted

实验3. 通过YAML文件部署容器

除了使用 kubectl 直接部署容器以外,还可以通过 YAML文件的方式部署容器。

3.1 创建 Deployment

最常见的Kubernetes对象之一是deployment对象。deployment对象定义了所需的容器规范,以及Kubernetes的其他部分用于发现和连接到应用程序的名称和标签。

查看 nginx-deployment.yaml 文件。该定义实现了基于nginx:alpine镜像启动容器,并开放容器的80端口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# cat /k8s/nginx-deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: webapp1
spec:
replicas: 1
template:
metadata:
labels:
app: webapp1
spec:
containers:
- name: webapp1
image: nginx:alpine
ports:
- containerPort: 80

使用以下命令部署 nginx-deployment.yaml

1
2
3
# cd /k8s
# kubectl create -f nginx-deployment.yaml
deployment "webapp1" created

image-20230401171420463

查看deployment状态

1
2
3
# kubectl get deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
webapp1 1 1 1 1 7s

image-20230401171427721

查看详细信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# kubectl describe deployment webapp1
Name: webapp1
Namespace: default
CreationTimestamp: Fri, 03 May 2019 14:07:14 +0000
Labels: app=webapp1
Annotations: deployment.kubernetes.io/revision=1
Selector: app=webapp1
Replicas: 1 desired | 1 updated | 1 total | 1 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 1 max unavailable, 1 max surge
Pod Template:
Labels: app=webapp1
Containers:
webapp1:
Image: katacoda/docker-http-server:latest
Port: 80/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
OldReplicaSets: <none>
NewReplicaSet: webapp1-65d887cc9f (1/1 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 56s deployment-controller Scaled up replica set webapp1-65d887cc9f to 1

3.2 创建 Service

Kubernetes具有强大的网络功能,可控制应用程序的通信方式。 这些网络配置也可以通过YAML进行控制。

查看 nginx-service.yaml。该service将主机的30080端口映射到容器的80端口,服务选择标签为webapp1的所有应用程序。在部署多个副本或实例时,它们将根据此公共标签自动进行负载均衡。该服务通过NodePort提供应用服务。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# cat /k8s/nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
name: webapp1-svc
labels:
app: webapp1
spec:
type: NodePort
ports:
- port: 80
nodePort: 30080
selector:
app: webapp1

image-20230401171440826

通过 kubectl 部署 service

1
2
# kubectl apply -f nginx-service.yaml
service "webapp1-svc" created

image-20230401171446764

查看 service 状态

1
2
3
4
5
# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
first-deployment NodePort 10.99.229.208 <none> 80:30826/TCP 1m
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3m
webapp1-svc NodePort 10.110.18.126 <none> 80:30080/TCP 4s

image-20230401171458546

查看 service 详细信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# kubectl describe svc webapp1-svc
Name: webapp1-svc
Namespace: default
Labels: app=webapp1
Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"app":"webapp1"},"name":"webapp1-svc","namespace":"default"},"spec":{"ports"...
Selector: app=webapp1
Type: NodePort
IP: 10.110.5.113
Port: <unset> 80/TCP
TargetPort: 80/TCP
NodePort: <unset> 30080/TCP
Endpoints: 172.18.0.4:80
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>

image-20230401171506850

3.3 测试

1
# curl localhost:30080

image-20230401171510862