前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >部署应用到 k8s 入门教程

部署应用到 k8s 入门教程

原创
作者头像
谢正伟
修改2021-05-08 17:03:32
5.9K0
修改2021-05-08 17:03:32
举报
文章被收录于专栏:云原生研究云原生研究

本篇文章适合k8s入门参考,使用 yaml 文件和 kubectl 命令完成应用部署。本文的脚本只演示了最基础的配置。

前提条件

  • 已经部署好 K8S 集群;
  • 本地安装了docker, kubectl;
  • kubectl 可以顺利访问集群;

Step 1: 使用 docker 打包镜像

1 编写 Dockerfile 文件。

示例如下:

代码语言:txt
复制
# 从官方的node镜像开始
FROM node:13-alpine

# 创建目录 /app
RUN mkdir /app
# 设置工作目录
WORKDIR /app
# 在 /app 内安装 mysql 依赖
RUN npm i mysql

上面的例子没有加入业务代码,并且没有入口文件,原因将在下文解释。

2 打包镜像

使用如下的命令将第一步的文件进行打包:

代码语言:txt
复制
# 如果上一步的文件名字为 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 的具体位置。
  • 别忘记后面有一个 点 .

3 推送镜像到远程服务器

命令如下:

代码语言:txt
复制
docker push your-name/node-base:1.0
# 或者 
docker push ccr.ccs.tencentyun.com/your-name/node-base:1.0

push 之前需要 login,请参考提供商的文档进行即可。

4 镜像分层

在第一步中,你会发现 build 过程里最慢的命令是 RUN npm i mysql ,这个步骤是从远程服务器拉取依赖包到镜像中,一般的官方服务器都在国外,有些依赖包甚至会拉取失败。所以为了减少每次等待时间,我们会将第一步产生的镜像作为基础镜像。

下面,我们为业务代码打包镜像,Dockerfile 如下:

代码语言:txt
复制
FROM ccr.ccs.tencentyun.com/your-name/node-base:1.0

COPY . /app
WORKDIR /app


# 入口文件。在 k8s 中,建议把入口配置在 k8s 的配置中。
# ENTRYPOINT [ "node", "index.js" ]

这一步仅拷贝了本地业务代码,build 的速度非常快。(请别忘记添加 gitignore 或者 gitignore 文件排除非必要文件)。

代码语言:txt
复制
docker build -t ccr.ccs.tencentyun.com/your-name/biz:1.0 .

5 本地测试

使用 docker images  命令可以看到刚刚 build 的镜像全部都在本地。想要直接运行镜像测试一下可以使用下面的命令:

代码语言:txt
复制
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 

执行上述命令就可以直接运行你的应用并进入到了 交互界面。这时候你可以在里面随便造了。

测试没问题后,可以上传你的镜像。

Step 2: 部署到 K8S

下面我们就要开始操作 k8s 集群了。

1 创建 namespace

为了方便后期的管理,一般不建议将业务镜像部署到 default 命名空间。使用如下的命令创建命名空间:

代码语言:txt
复制
kubectl create namespace your-biz-ns

相对于命令式,k8s 更加推崇的是声明式运维。上面创建namespace 的操作,可以通过如下的 yaml 文件表示。

假设下面的代码 文件名为 ns.yaml,一般情况下会把这个文件随着代码一起保存在代码仓库中。

代码语言:txt
复制
apiVersion: v1
kind: Namespace
metadata:
  name: your-biz-ns
spec:
  finalizers:
    - kubernetes

将上面的 ns.yaml 文件执行一下:

代码语言:txt
复制
kubectl apply -f ns.yaml

kubectl apply 命令可以完成创建或者修改的动作。

2 部署应用

同样,我们需要编写一个 yaml 来“声明”应用的部署状态。(文件名为:app.yaml)

代码语言:txt
复制
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:

代码语言:txt
复制
kubectl apply -f app.yaml

完成之后,通过下面的命令我们可以查看刚刚的部署:

代码语言:txt
复制
# 查看命名空间
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

3 使用 Service 暴露应用

在 k8s 里,可以使用 service 暴露服务,一个 LoadBalancer 的 service 示例如下:

代码语言:txt
复制
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 的简写):

代码语言:txt
复制
kubectl get svc -n your-biz-ns

可以看到 EXTERNAL-IP 信息,这个 ip 就是对外的 ip,现在可以在浏览器中直接访问这个 ip 了。

4 创建 Ingress

在更通用的情况下,我们需要通过域名或路径来暴露并路由服务,此时可以使用 Ingress 配合内网的 service 来暴露服务。使用这种方式,则无需创建 上面步骤的 LoadBalancer 的 service。

创建一个内网 Service:

代码语言:txt
复制
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:

代码语言:txt
复制
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 的配置类似如下:

代码语言:txt
复制
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 的能力远远不止于此。下面的一些议题请继续研究:

  • 坑:本文未给私有镜像配置密钥,拉取镜像会失败,请自行配置。
  • 为容器限定运行资源,指定容器的运行需要的CPU和内存(关键词:requests, limits)。
  • 给容器配置探测器,让你的应用真正保活(关键词:livenessProbe, readinessProbe)。
  • 使用 k8s 管理配置文件(关键词:ConfigMap)。
  • k8s 存储挂载(关键词:volumes, volumeMounts, PV, PVC)。
  • 如何在集群内隔离容器(关键词:NetworkPolicy)。
  • 如何控制某些节点只能部署或者不能部署某些应用(关键词:污点 taint,容忍 tolerations,亲和 affinity)。
  • 为集群配置自动水平伸缩(关键词 HPA)。
  • 其他类型的工作负载(StatefulSets, DaemonSet, Job 等)。
  • 如何监控集群,如何收集系统和应用日志?
  • 如何在集群内部进行东西向调用,并监测调用过程,并操控流量(关键词:istio, service mesh)。
  • 如何结合 k8s 创建一个健全的 DevOps 体系?
  • ...

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前提条件
  • Step 1: 使用 docker 打包镜像
    • 1 编写 Dockerfile 文件。
      • 2 打包镜像
        • 3 推送镜像到远程服务器
          • 4 镜像分层
            • 5 本地测试
            • Step 2: 部署到 K8S
              • 1 创建 namespace
                • 2 部署应用
                  • 3 使用 Service 暴露应用
                    • 4 创建 Ingress
                    • 精进
                    相关产品与服务
                    容器服务
                    腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档