千里之行,始于足下html
当咱们新学习一门编程语言时,老是从 hello, world
开始。nginx
当咱们学习如何在 k8s 上部署应用时,部署一个简单的 nginx
,可以访问到它的配置页面。因为它五脏俱全,功能简单,无状态,能够当作 k8s 部署应用的 hello, world
。git
本篇文章将学习如何使用 Pod
,Deployment
与 Service
开始部署第一个应用github
若是对你可以有所帮助,能够帮我在 shfshanyue/op-note 上点个 star。web
pod
是 kubernetes
中最小的编排单位,一般由一个容器组成 (有时候会有多个容器组成)。docker
如下是一个 pod 资源配置文件的最小示例,关于详细配置参考 kubernetes v1.16 Podshell
咱们使用 nginx:alpine
做为镜像部署了一个 Pod
,而且暴露了 80 端口编程
apiVersion: v1
kind: Pod
metadata:
name: nginx
# 指定 label,便于检索
labels:
app: nginx
spec:
containers:
- name: nginx
# 指定镜像
image: nginx:alpine
# 指定暴露端口
ports:
- containerPort: 80
复制代码
使用 kubectly apply
,部署 Pod后端
$ kubectl apply -f nginx.yaml
pod/nginx created
复制代码
校验部署状态,此时 STATUS 为 Running
代表部署成功api
# 获取 Pod 部署的状态,特别是 IP
# -o wide 列出IP/Node等更多信息
$ kubectl get pods nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 14m 10.244.1.9 shuifeng <none> <none>
复制代码
使用 -o wide
获取到 pod 的 IP 地址,访问该 IP 查看是否可以访问到 nginx
经典的配置页面
# 获取更加详细的信息
$ kubectl describe pod nginx
# 每一个 pod 都有一个IP地址,直接访问IP地址获取内容
$ curl 10.244.1.9
<!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>
复制代码
此时咱们可使用 kubectl exec
进入 Pod
的内部容器。若是 Pod
中有多个容器,使用 kubectl exec -c
指定容器
$ kubectl exec -it nginx sh
复制代码
在 Pod
容器中执行命令,校验其中的 socket
状况以及 nginx 服务
# 在 POD 中执行命令
# 能够看到 nginx 起的80端口
$ netstat -tan
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
# 访问 nginx,正确返回配置页面的内容
# -q: 不输出 wget 自身信息
# -O -: 定向到标准输出
$ wget -q -O - localhost
<!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>
复制代码
在 k8s
中编排应用能够更好地作弹性扩容,负载均衡。既然要均衡,一个 Pod 确定不能均衡,天然要部署多个 Pod
docker-compose
能够简单地经过 docker-compose scale
来扩容,k8s
更不在话下了。
在k8s中管理 Pod
的称做 Controller
,咱们可使用 Deployment
这种 Controller
来为 Pod
进行扩容,固然它还能够滚动升级,回滚,金丝雀等等关于部署的事情
咱们编写一个 Deployment
的资源配置文件
spec.template
: 指定要部署的 Podspec.replicas
: 指定要部署的个数spec.selector
: 定位须要管理的 PodapiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
复制代码
咱们使用 kubectl apply
部署生效后查看 Pod
以及 Deployment
状态
$ kubectl apply -f nginx.yaml
# nginx-deployment 部署的三个 pod 所有成功
$ kubectl get pods -o wide -l 'app=nginx'
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 1 4h29m 10.244.1.9 shuifeng <none> <none>
nginx-deployment-54f57cf6bf-57g8l 1/1 Running 0 23m 10.244.1.10 shuifeng <none> <none>
nginx-deployment-54f57cf6bf-ltdf7 1/1 Running 0 23m 10.244.1.11 shuifeng <none> <none>
nginx-deployment-54f57cf6bf-n8ppt 1/1 Running 0 23m 10.244.1.12 shuifeng <none> <none>
# READY 3/3 代表所有部署成功
$ kubectl get deploy nginx-deployment
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 23m
复制代码
如今咱们已经部署了一个 Deployment,其中有三个 Pod,就有三个 IP,那咱们如何向这三个 Pod 请求服务呢,况且每当上线部署后,就会产生新的 Pod IP。即咱们如何作服务发现
咱们能够经过 Service
解决这个问题,作指定 Deployment
或者特定集合 Pod
的网络层抽象
配置文件以下
spec.selector
: 指定如何选择 Pod
spec.ports
: 指定如何暴露端口apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
复制代码
咱们使用 kubectl apply
部署生效后查看 Service
状态
$ kubectl get svc nginx-service -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
nginx-service ClusterIP 10.108.9.49 <none> 80/TCP 11m app=nginx
复制代码
ClusterIP
表明服务只能在集群内部访问,此时咱们访问 10.108.9.49
访问服务
$ curl 10.108.9.49
<!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>
复制代码
服务发现,咱们只须要知道服务的名字便可以访问服务,只能经过 IP 访问也太 low 了。Service
固然不会这么 low
在 k8s 中,全部的服务能够经过 my-svc.my-namespace.svc.cluster.local
作服务发现,对于刚才部署的 Service 就是 nginx-service.default.svc.cluster.local
在集群中的任意一个 Pod 中经过域名访问服务,访问成功
$ curl nginx-service.default.svc.cluster.local
<!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>
复制代码
经过配置 Deployment
与 Service
,此时咱们能够在集群中经过服务发现访问域名。完整的配置文件以下
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
复制代码
当咱们仍然须要把服务暴露给互联网,那咱们如何在集群外访问域名呢?
欢迎关注公众号山月行,我会按期分享一些先后端以及运维的文章,而且会有技术与生活上的每日回顾与总结,欢迎关注交流