本篇文章适合k8s入门参考,使用 yaml 文件和 kubectl 命令完成应用部署。本文的脚本只演示了最基础的配置。
示例如下:
# 从官方的node镜像开始
FROM node:13-alpine
# 创建目录 /app
RUN mkdir /app
# 设置工作目录
WORKDIR /app
# 在 /app 内安装 mysql 依赖
RUN npm i mysql
上面的例子没有加入业务代码,并且没有入口文件,原因将在下文解释。
使用如下的命令将第一步的文件进行打包:
# 如果上一步的文件名字为 Dockerfile 并且执行命令的位置在同一个目录。
docker build -t your-name/node-base:1.0 .
# 如果文件名不是 Dockerfile 或者命令执行位置不同。
docker build -t your-name/node-base:1.0 -f dockerfilePath .
上面的命令中:
-t node-base:1.0
表示给这个镜像打标签,这个是为下一步推送准备的,私有docker 镜像服务器一般会提供完整域名作为前缀,如腾讯云的 TCR 表示为: -t ccr.ccs.tencentyun.com/your-name/node-base:1.0
。-f dockerfilePath
表示docker file 的具体位置。.
。命令如下:
docker push your-name/node-base:1.0
# 或者
docker push ccr.ccs.tencentyun.com/your-name/node-base:1.0
push 之前需要 login,请参考提供商的文档进行即可。
在第一步中,你会发现 build 过程里最慢的命令是 RUN npm i mysql
,这个步骤是从远程服务器拉取依赖包到镜像中,一般的官方服务器都在国外,有些依赖包甚至会拉取失败。所以为了减少每次等待时间,我们会将第一步产生的镜像作为基础镜像。
下面,我们为业务代码打包镜像,Dockerfile 如下:
FROM ccr.ccs.tencentyun.com/your-name/node-base:1.0
COPY . /app
WORKDIR /app
# 入口文件。在 k8s 中,建议把入口配置在 k8s 的配置中。
# ENTRYPOINT [ "node", "index.js" ]
这一步仅拷贝了本地业务代码,build 的速度非常快。(请别忘记添加 gitignore 或者 gitignore 文件排除非必要文件)。
docker build -t ccr.ccs.tencentyun.com/your-name/biz:1.0 .
使用 docker images
命令可以看到刚刚 build 的镜像全部都在本地。想要直接运行镜像测试一下可以使用下面的命令:
docker run --rm -it ccr.ccs.tencentyun.com/your-name/biz:1.0 sh
# 或者这样:(下面的 7af6c817aa0a 是使用 docker images 命令看到的镜像 id)
docker run --rm -it 7af6c817aa0a sh
上面的命令中:
--rm
表示退出后删除这个容器实例。-it
表示进入交互模式(分别是 -i, -t 两个参数)。sh
表示进入容器后执行的命令。具体可以查看 docker run --help
执行上述命令就可以直接运行你的应用并进入到了 交互界面。这时候你可以在里面随便造了。
测试没问题后,可以上传你的镜像。
下面我们就要开始操作 k8s 集群了。
为了方便后期的管理,一般不建议将业务镜像部署到 default 命名空间。使用如下的命令创建命名空间:
kubectl create namespace your-biz-ns
相对于命令式,k8s 更加推崇的是声明式运维。上面创建namespace 的操作,可以通过如下的 yaml 文件表示。
假设下面的代码 文件名为 ns.yaml,一般情况下会把这个文件随着代码一起保存在代码仓库中。
apiVersion: v1
kind: Namespace
metadata:
name: your-biz-ns
spec:
finalizers:
- kubernetes
将上面的 ns.yaml 文件执行一下:
kubectl apply -f ns.yaml
kubectl apply
命令可以完成创建或者修改的动作。
同样,我们需要编写一个 yaml 来“声明”应用的部署状态。(文件名为:app.yaml)
apiVersion: apps/v1
kind: Deployment
metadata:
name: biz-deployment
namespace: your-biz-ns
labels:
app: biz
spec:
replicas: 2
selector:
matchLabels:
app: biz
template:
metadata:
labels:
app: biz
spec:
containers:
- image: ccr.ccs.tencentyun.com/your-name/biz:1.0
imagePullPolicy: IfNotPresent
name: biz
args:
- node
- index.js
ports:
- containerPort: 7304
上面的例子中:
metadata.name
表示这个部署的名字为 biz-deployment,这个名字你自己取。下面的 namespace 表示我们要把应用部署到 your-biz-ns 这个命名空间。spec.replicas
表示这个部署需要创建 2 个副本(实例)。spec.selector
表示这个 Deployment 如何找到要管理的的 pods。如果要找到biz应用,只需要找到标签里有 app=biz 的 pods 即可。所以在这个文件中, spec.selector
和 spec.template.metadata
中的标签需要匹配上。template.spec
里是具体的Pod 配置。containers[].image
是镜像地址, imagePullPolicy: IfNotPresent
表示如果当前镜像不在宿主机上,就取镜像仓库拉。containers[].args
是容器的入口命令,k8s 允许重新指定容器的入口。实际上我们可以在这个文件里配置一些变量,并可以为入口指定动态参数。ports[].containerPort
是你的应用实际上启动的端口(容器内的端口)。上述文件定义了我们希望应用达到的状态:需要启动 2 个实例,标签是 app=biz,镜像使用 your-name/biz:1.0,端口在 7304 等。k8s 会在接收到这个文件后,将集群的应用调整到我们希望的状态。
将这个配置告诉 k8s:
kubectl apply -f app.yaml
完成之后,通过下面的命令我们可以查看刚刚的部署:
# 查看命名空间
kubectl get namespaces
# 或者
kubectl get namespace
# 或者
kubectl get ns
# k8s 的关键字基本都可以简写,简写列表请查阅官方文档。
# 查看部署。-n 指定了命名空间
kubectl get deploy -n your-biz-ns
# 查看 pod。这里没写错,-n 可以后面没有空格
kubectl get po -nyour-biz-ns
在 k8s 里,可以使用 service 暴露服务,一个 LoadBalancer 的 service 示例如下:
apiVersion: v1
kind: Service
metadata:
name: biz-service
namespace: your-biz-ns
spec:
type: LoadBalancer
selector:
app: biz
ports:
- protocol: TCP
port: 80
targetPort: 7304
上面的配置中,我们将标记为 app=biz 的 pod 的端口 7304 映射到负载均衡的 80 端口。
使用 kubectl apply 应用一下。
查看刚刚创建的 service (svc 是 service 的简写):
kubectl get svc -n your-biz-ns
可以看到 EXTERNAL-IP 信息,这个 ip 就是对外的 ip,现在可以在浏览器中直接访问这个 ip 了。
在更通用的情况下,我们需要通过域名或路径来暴露并路由服务,此时可以使用 Ingress 配合内网的 service 来暴露服务。使用这种方式,则无需创建 上面步骤的 LoadBalancer 的 service。
创建一个内网 Service:
apiVersion: v1
kind: Service
metadata:
name: biz-service-inner
namespace: your-biz-ns
spec:
selector:
app: biz
ports:
- protocol: TCP
port: 80
targetPort: 7304
上面的配置删除了 type: LoadBalancer
,默认的 Service 使用的是 ClusterIp 模式,这种 Service 只能集群内部的 Pod 中访问。
创建 Ingress:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-corp-ingress
namespace: your-biz-ns
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: "www.mycorp.com"
http:
paths:
- path: /biz
pathType: Prefix
backend:
service:
name: biz-service-inner
port:
number: 80
上述 Ingress 配置将域名“www.mycorp.com” 并且路径是 /biz 开头的流量导向了 biz-service-inner这个服务。
请注意:这个配置是 k8s 官方配置,各厂商对于 Ingress 的实现方式不一致,此处的配置需要参考提供商的文档进行 修改。
如在 nginx-ingress 的配置类似如下:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: "your-nginx-ingress-instance-id"
name: nginx-ingress
namespace: your-biz-ns
spec:
rules:
- http:
paths:
- backend:
serviceName: biz-service-inner
servicePort: 80
到这里,你已经把你到应用部署到了 k8s 集群中。但 k8s 的能力远远不止于此。下面的一些议题请继续研究:
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。