首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >本地 k8s 部署

本地 k8s 部署

原创
作者头像
谛听
修改2022-04-11 10:40:35
修改2022-04-11 10:40:35
2.4K0
举报
文章被收录于专栏:随意记录随意记录

1 目标

在本地,一键启动 k8s 集群,并将服务部署到 k8s 集群上。

2 部署 k8s

2.1 部署 minikube

minikube 是一个虚拟机,启动后会在内部自动创建一个 k8s 集群。minikube 是 k8s 的 node。

2.1.1 安装 minikube

minikube 安装:

代码语言:txt
复制
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube

2.1.2 启动 minikube

代码语言:txt
复制
minikube start \
        --extra-config=apiserver.service-node-port-range=1-65535 \
        --listen-address=0.0.0.0

其中,

  • --extra-config 用来修改 minikube 默认暴露给主机的端口范围,默认为:30000-32767。
  • --listen-address=0.0.0.0 是为了将 minikube 内部的服务暴露在 minikube 外部,或者也可以使用 ingress-nginx 插件。minikube 暴露给主机的地址为 192.168.49.2,假如 minikube 中服务监听的端口为 3000,则在主机上访问该服务的方式为 192.168.49.2:3000。可以用 minikube service --url <service-name> 命令查看服务地址,例如:$ minikube service --url signaling-0 http://192.168.49.2:21116

2.1.3 kubectl

kubectl 可方便地与 k8s 集群进行交互。minikube 内部默认安装 kubectl,例如查看所有 pod:

代码语言:txt
复制
minikube kubectl -- get pods

可以为 minikube kubectl -- 命令起一个别名:

代码语言:txt
复制
alias kubectl="minikube kubectl --"

查看所有 pod 命令可简化为:

代码语言:txt
复制
kubectl get pods

kubectl 常用的命令:

  • 列出 pod,service 等资源:# List all pods in plain-text output format. kubectl get pods

List all services in plain-text output format.

kubectl get svc

List all daemon sets in plain-text output format.

kubectl get ds

代码语言:txt
复制
  • 查看 pod 等资源的状态,事件等:# Display the details of all the pods that are managed by the replication controller named <rc-name>.Remember: Any pods that are created by the replication controller get prefixed with the name of the replication controller.kubectl describe pods <rc-name>
  • 进入 pod 中的容器:# Get an interactive TTY and run /bin/bash from pod <pod-name>. By default, output is from the first container. kubectl exec -it <pod-name> -- /bin/bash

说明:pod 是 k8s 的管理单元,pod 中可包含多个容器,pod 中的所有容器共享 namespace。

2.1.4 其它命令

停止 minikube:

代码语言:txt
复制
minikube stop

删除 k8s 集群:

代码语言:txt
复制
minikube delete

2.2 部署 Lens

Lens 是 k8s 集群的操作界面,可方便地与 k8s 集群进行交互。

2.2.1 安装 Lens

代码语言:txt
复制
wget https://api.k8slens.dev/binaries/Lens-5.4.4-latest.20220325.1.amd64.deb
sudo dpkg -i Lens-5.4.4-latest.20220325.1.amd64.deb

2.2.2 启动 Lens

  1. 命令方式:
代码语言:txt
复制
lens
  1. 界面方式:在应用中搜索到 Lens 后双击。

2.2.3 Lens 管理 k8s

左边菜单栏中列出来 k8s 中的各种资源,可对各种资源进行查看、修改、删除。

例如,查看所有 pod:

查看所有 pod
查看所有 pod

对 Deployment 或 StatefulSet 扩缩容:

对 Deployment 或 StatefulSet 扩缩容
对 Deployment 或 StatefulSet 扩缩容

进入容器:

进入容器
进入容器

将 k8s 中 TCP 服务的端口映射到主机:

将 k8s 中 TCP 服务的端口映射到主机
将 k8s 中 TCP 服务的端口映射到主机

内置了 Helm,Helm 用来管理 k8s 应用,可发现、共享和使用为 k8s 构建的软件。

例如,在 k8s 安装 redis 或 nats:

安装 redis 或 nats
安装 redis 或 nats

3 部署 Nginx

部署:

代码语言:shell
复制
docker run -d --name xremote_nginx --network host \
           -v ${HOME}/nginx/nginx.conf:/etc/nginx/nginx.conf nginx

${HOME}/nginx/nginx.conf 中添加了要代理的 minikube 中的 UDP 服务端口。示例如下:

代码语言:shell
复制
stream {
  log_format proxy '$remote_addr [$time_local] '
                   '$protocol $status $bytes_sent $bytes_received '
                   '$session_time "$upstream_addr" '
                   '"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';

  access_log /var/log/nginx/udp-access.log proxy;
  open_log_file_cache off;

  upstream signaling-0 {
       server 192.168.49.2:21116;
  }
  server{
       listen 21116 udp reuseport;
       proxy_connect_timeout 8s;
       proxy_pass signaling-0;
  }
}

使用 Nginx 的原因:代理 minikube 中的 UDP 服务。

  • 使用 NodePort 等 service 可将 k8s 中的服务暴露给 node,也就是 minikube,而不是主机。
  • minikube 暴露给主机的地址默认为 192.168.49.2,假如 minikube 中服务监听的端口为 3000,则在主机上访问该服务的方式为 192.168.49.2:3000,而不是 ${host_ip}:3000。所以,如果需要从另外一台主机访问 minikube 中的服务,需要 nginx 进行代理。
  • 对于 minikube 中的 TCP 服务,可不通过 nginx 进行代理,可使用 kubectl port-forward 命令直接将端口映射到主机。

4 部署服务

4.1 部署文件

deployment.yml:定义资源如何部署。

代码语言:shell
复制
apiVersion: apps/v1
kind: Deployment
metadata:
  name: signaling-0
spec:
  selector:
    matchLabels:
      app: signaling-0
  replicas: 1
  template:
    metadata:
      labels:
        app: signaling-0
    spec:
      containers:
        - name: signaling
          image: code.com:6543/signaling-server:latest
          ports:
            - name: server
              containerPort: 21116
              protocol: UDP
          imagePullPolicy: IfNotPresent
          env:
            - name: RUN_XREMOTE_SERVER_MODE
              value: production
          command: ["/bin/bash"]
          args: ["-c", "/opt/signaling_server/run.sh"]
          volumeMounts:
            - name: config
              mountPath: /opt/signaling_server/config/signaling/production.toml
              subPath: production.toml
      volumes:
        - name: config
          configMap:
            name: signaling

字段说明:

  • kind:指定了这个 API 对象的类型是一个 Deployment。
  • Deployment:是一个定义多副本应用(即多个副本 Pod)的对象。此外,Deployment 还负责在 Pod 定义发生变化时,对每个副本进行滚动更新(Rolling Update)。
    • 场景:一个应用的所有 Pod,是完全一样的。所以,它们互相之间没有顺序,也无所谓运行在哪台宿主机上。
    • Pod :如果 k8s 看作操作系统,pod 可看作进程组,容器可看作进程。凡是调度、网络、存储,以及安全相关的属性,基本上是 Pod 级别的。Pod 里的所有容器,共享的是同一个 Network Namespace,并且可以声明共享同一个 Volume。
    • 另一种常见的 kind 是 StatefulSet,相对于 Deployment,一个应用的 Pod 之间存在着依赖关系,比如:主从关系、主备关系。redis 和 nats 是 StatefulSet。
  • metadata:是 API 对象的“标识”,即元数据,它也是我们从 Kubernetes 里找到这个对象的主要依据。
  • spec:用来描述它所要表达的功能。
  • spec.selector.matchLabels:过滤规则,一般称之为:Label Selector。这个字段一般和 spec.template.metadata.labels.app 保持一致,表示该 deployment 控制下面 spec 中定义的 Pod。 使用一种 API 对象(Deployment)管理另一种 API 对象(Pod)的方法,在 Kubernetes 中,叫作“控制器”模式(controller pattern)
  • spec.replicas:Pod 副本个数。
  • spec.template:Pod 模板,描述了我想要创建的 Pod 的细节。本例中,Pod 里只有一个容器,该容器的镜像(spec.containers.image)是 code.autox.ds:6543/internal/mapping-experimental/offboard/signaling-server:latest,监听端口(containerPort)是 21116,将 signaling 这个配置挂载到了 /opt/signaling_server/config/signaling/production.toml,后面会提到 ConfigMap。

config_map.yml:存储一些配置信息。

代码语言:shell
复制
apiVersion: v1
kind: ConfigMap
metadata:
  name: signaling
data:
  production.toml: |-
    debug = false

    [signaling]
    data_center = "beijing"
    service_name = "signaling"
    signaling_port = 21116

在 Kubernetes 中,有几种特殊的 Volume,它们的作用是为容器提供预先定义好的数据。所以,从容器的角度来看,这些 Volume 里的信息就是仿佛是被 K8s “投射”(Project)进入容器当中的。到目前为止,Kubernetes 支持的 Projected Volume 一共有四种:Secret、ConfigMap、Downward API 和 ServiceAccountToken。

前面的 deployment.yml 中的 spec.template.spec.volumes 中会声明一个 volume,该 volume 的来源是一个 ConfigMap,然后该 volume 会被挂载到 /opt/signaling_server/config/signaling/production.toml。

service.yml:service 的种类较多,其中 NodePort 的作用是将服务端口暴露在 k8s 外部。

代码语言:shell
复制
kind: Service
apiVersion: v1
metadata:
  name: signaling-0
spec:
  ports:
    - name: server
      nodePort: 21116
      port: 21116
      targetPort: 21116
      protocol: UDP
  selector:
    app: signaling-0
  type: NodePort

将服务暴露在集群外的方式:

  • Service
  • NodePort:最简单。
  • LoadBalancer:适用于公有云。
  • ExternalName:Kubernetes 在 1.7 之后支持的一个新特性。
  • Ingress:是 Service 的“Service”。

本例中:

  • type=NodePort
  • ports 字段
    • nodePort:暴露在集群外部的端口。
    • port:暴露在集群内部的端口。
    • targetPort:容器监听的端口。
  • selector 字段表示它代理的是 signaling-0 这个 Pod 的端口。

要访问这个 Service,只需要访问:<node 的 IP 地址>:21116

  • 另一种 service:ClusterIP
    • 将服务暴露在集群内部,即在集群中的一个 pod 内部可访问到另一个 pod。nats 和 redis 有用到。
    • 当 ClusterIP 中将 clusterIP 字段设置为 None,便不会被分配 VIP,被称为 Headless Service,它所代理的所有 Pod 的 IP 地址,都会被绑定一个 DNS 记录,形式为 <name>.<namespace>。例如,redis 的 headless 定义如下: apiVersion: v1 kind: Service metadata: name: redis-headless namespace: default spec: ... clusterIP: None type: ClusterIP ...

以上几个 yml 文件也可以放在一个 yml 文件中,并以 ”---“ 分隔。

4.2 部署

对每个 yml 文件执行:

代码语言:shell
复制
kubectl apply -f xxx.yml

5 查看日志

方式 1)Lens 界面方式:

查看日志
查看日志

方式 2)命令行方式:

代码语言:txt
复制
$ kubectl get pods
NAME                          READY   STATUS    RESTARTS      AGE
discovery-568569c86f-jflrq    1/1     Running   1 (51m ago)   58m

$ kubectl exec -it discovery-568569c86f-jflrq -- /bin/sh
# ls  
config	discovery-server  log  run.sh  sum.md5
# ls log   
discovery_server_20220408-0607.log

说明:由于 服务的日志写在了文件中,而不是标准输出中,所以用 kubectl logs 命令看不到日志。

6 错误处理

6.1 拉取镜像失败

发生 ErrImagePull 错误:

代码语言:txt
复制
$ kubectl get pods
NAME                          READY   STATUS             RESTARTS   AGE
discovery-568569c86f-njmf4    0/1     ErrImagePull       0          41m

是因为 minikube 没有权限拉取镜像。

解决:

代码语言:txt
复制
minikube -p minikube docker-env
eval $(minikube -p minikube docker-env)
cd xremote/server
bash release_build.sh discovery

相当于把镜像 push 到了 minikube 中。

或者这种方式应该也可以:https://minikube.sigs.k8s.io/docs/handbook/untrusted_certs/ ,本人没有尝试。

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 目标
  • 2 部署 k8s
    • 2.1 部署 minikube
      • 2.1.1 安装 minikube
      • 2.1.2 启动 minikube
      • 2.1.3 kubectl
  • List all services in plain-text output format.
  • List all daemon sets in plain-text output format.
    • 2.1.4 其它命令
    • 2.2 部署 Lens
      • 2.2.1 安装 Lens
      • 2.2.2 启动 Lens
      • 2.2.3 Lens 管理 k8s
  • 3 部署 Nginx
  • 4 部署服务
    • 4.1 部署文件
    • 4.2 部署
  • 5 查看日志
  • 6 错误处理
    • 6.1 拉取镜像失败
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档