前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >下篇1:将 ConfigMap 中的键值对作为容器的环境变量

下篇1:将 ConfigMap 中的键值对作为容器的环境变量

作者头像
不背锅运维
发布2023-05-26 08:49:20
2.2K0
发布2023-05-26 08:49:20
举报
文章被收录于专栏:监控监控

写在开篇

继续接上篇,《一文了解K8S的ConfigMap》。上篇聊过,官方文档中提到的可以使用下面4种方式来使用 ConfigMap 配置 Pod 中的容器:

  • 容器的环境变量:可以将 ConfigMap 中的键值对作为容器的环境变量。
  • 在只读卷里面添加一个文件,让应用来读取:可以将 ConfigMap 中的内容作为一个只读卷挂载到 Pod 中的容器内部,然后在容器内读取挂载的文件。
  • 编写代码在 Pod 中运行,使用 Kubernetes API 来读取 ConfigMap:可以在 Pod 中运行自定义代码,使用 Kubernetes API 来读取 ConfigMap 中的内容。
  • 在容器命令和参数内:可以在容器的启动命令中通过引用环境变量的方式来使用 ConfigMap。

为了控制篇幅,计划分4篇进行分享,本篇分享以使用“容器的环境变量”的方式进行实战。 关于使用ConfigMap的更多详情,可参考官方文档:https://kubernetes.io/zh-cn/docs/concepts/configuration/configmap/#using-configmaps

开发示例应用

  1. goweb项目目录结构

<!---->

代码语言:txt
复制
[root@workhost goweb]# tree
代码语言:txt
复制
.
代码语言:txt
复制
├── Dockerfile
代码语言:txt
复制
├── go.mod
代码语言:txt
复制
├── main.go
代码语言:txt
复制
├── README.md
代码语言:txt
复制
└── static
代码语言:txt
复制
    └── login.html
  1. main.go

<!---->

代码语言:txt
复制
package main
代码语言:txt
复制
import (
代码语言:txt
复制
        "fmt"
代码语言:txt
复制
        "log"
代码语言:txt
复制
        "net/http"
代码语言:txt
复制
        "os"
代码语言:txt
复制
        "text/template"
代码语言:txt
复制
)
代码语言:txt
复制
type Message struct {
代码语言:txt
复制
        Msg string
代码语言:txt
复制
}
代码语言:txt
复制
func home(w http.ResponseWriter, r *http.Request) {
代码语言:txt
复制
        if r.Method == "GET" {
代码语言:txt
复制
                w.Header().Set("Location", "/login")
代码语言:txt
复制
                w.WriteHeader(http.StatusFound)
代码语言:txt
复制
        }
代码语言:txt
复制
}
代码语言:txt
复制
func login(w http.ResponseWriter, r *http.Request) {
代码语言:txt
复制
        t, _ := template.ParseFiles("./static/login.html")
代码语言:txt
复制
        if r.Method == "GET" {
代码语言:txt
复制
                t.Execute(w, nil)
代码语言:txt
复制
        }
代码语言:txt
复制
}
代码语言:txt
复制
func main() {
代码语言:txt
复制
        http.HandleFunc("/", home)
代码语言:txt
复制
        http.HandleFunc("/login", login)
代码语言:txt
复制
        args := os.Args
代码语言:txt
复制
        if args[1] == "-p" {
代码语言:txt
复制
                port := args[2]
代码语言:txt
复制
                listenAddr := fmt.Sprintf(":%v", port)
代码语言:txt
复制
                log.Println("ListenAndserve", listenAddr)
代码语言:txt
复制
                err := http.ListenAndServe(listenAddr, nil)
代码语言:txt
复制
                if err != nil {
代码语言:txt
复制
                        log.Println(err)
代码语言:txt
复制
                }
代码语言:txt
复制
        }
代码语言:txt
复制
}

本次代码在上次的基础上做了点小改造:接受命令行参数,使用 os.Args 获取程序运行时的参数。如果传入的参数中包含 -p,则说明需要指定监听的端口,将端口值读取出来并使用 http.ListenAndServe 启动 HTTP 服务。

  1. login.html

<!---->

代码语言:txt
复制
<!DOCTYPE html>
代码语言:txt
复制
<html>
代码语言:txt
复制
  <head>
代码语言:txt
复制
    <meta charset="UTF-8">
代码语言:txt
复制
    <title>Login K8S</title>
代码语言:txt
复制
    <style>
代码语言:txt
复制
      body {
代码语言:txt
复制
        background-color: #f2f2f2;
代码语言:txt
复制
        font-family: Arial, sans-serif;
代码语言:txt
复制
      }
代码语言:txt
复制
      #login-box {
代码语言:txt
复制
        background-color: #fff;
代码语言:txt
复制
        border-radius: 5px;
代码语言:txt
复制
        box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
代码语言:txt
复制
        margin: 100px auto;
代码语言:txt
复制
        max-width: 400px;
代码语言:txt
复制
        padding: 20px;
代码语言:txt
复制
      }
代码语言:txt
复制
      h1 {
代码语言:txt
复制
        font-size: 24px;
代码语言:txt
复制
        margin: 0 0 20px;
代码语言:txt
复制
        text-align: center;
代码语言:txt
复制
      }
代码语言:txt
复制
      label {
代码语言:txt
复制
        display: block;
代码语言:txt
复制
        font-size: 14px;
代码语言:txt
复制
        font-weight: bold;
代码语言:txt
复制
        margin-bottom: 5px;
代码语言:txt
复制
      }
代码语言:txt
复制
      input[type="text"],
代码语言:txt
复制
      input[type="password"] {
代码语言:txt
复制
        border-radius: 3px;
代码语言:txt
复制
        border: 1px solid #ccc;
代码语言:txt
复制
        box-sizing: border-box;
代码语言:txt
复制
        font-size: 14px;
代码语言:txt
复制
        padding: 10px;
代码语言:txt
复制
        width: 100%;
代码语言:txt
复制
      }
代码语言:txt
复制
      input[type="submit"] {
代码语言:txt
复制
        background-color: #007bff;
代码语言:txt
复制
        border: none;
代码语言:txt
复制
        border-radius: 3px;
代码语言:txt
复制
        color: #fff;
代码语言:txt
复制
        cursor: pointer;
代码语言:txt
复制
        font-size: 14px;
代码语言:txt
复制
        padding: 10px;
代码语言:txt
复制
        width: 100%;
代码语言:txt
复制
      }
代码语言:txt
复制
      input[type="submit"]:hover {
代码语言:txt
复制
        background-color: #0069d9;
代码语言:txt
复制
      }
代码语言:txt
复制
      .error-message {
代码语言:txt
复制
        color: #dc3545;
代码语言:txt
复制
        font-size: 14px;
代码语言:txt
复制
        margin: 10px 0;
代码语言:txt
复制
        text-align: center;
代码语言:txt
复制
      }
代码语言:txt
复制
    </style>
代码语言:txt
复制
  </head>
代码语言:txt
复制
  <body>
代码语言:txt
复制
    <div id="login-box">
代码语言:txt
复制
      <h1>容器云管理平台</h1>
代码语言:txt
复制
      <form>
代码语言:txt
复制
        <label for="username">账号:</label>
代码语言:txt
复制
        <input type="text" id="username" name="username">
代码语言:txt
复制
        <label for="password">密码:</label>
代码语言:txt
复制
        <input type="password" id="password" name="password">
代码语言:txt
复制
        <input type="submit" value="登录">
代码语言:txt
复制
      </form>
代码语言:txt
复制
      <div class="error-message"></div>
代码语言:txt
复制
    </div>
代码语言:txt
复制
    <script>
代码语言:txt
复制
      const form = document.querySelector('form');
代码语言:txt
复制
      const errorMessage = document.querySelector('.error-message');
代码语言:txt
复制
      form.addEventListener('submit', function(event) {
代码语言:txt
复制
        event.preventDefault();
代码语言:txt
复制
        const username = document.getElementById('username').value;
代码语言:txt
复制
        const password = document.getElementById('password').value;
代码语言:txt
复制
        if (username === '' || password === '') {
代码语言:txt
复制
          errorMessage.textContent = 'Please enter a username and password.';
代码语言:txt
复制
        } else if (username !== 'admin' || password !== 'password') {
代码语言:txt
复制
          errorMessage.textContent = 'Incorrect username or password.';
代码语言:txt
复制
        } else {
代码语言:txt
复制
          alert('Login successful!');
代码语言:txt
复制
        }
代码语言:txt
复制
      });
代码语言:txt
复制
    </script>
代码语言:txt
复制
  </body>
代码语言:txt
复制
</html>

实战:以使用“容器的环境变量”的方式

  1. 制作镜像

编写Dockerfile:

代码语言:txt
复制
FROM alpine:latest
代码语言:txt
复制
WORKDIR /app
代码语言:txt
复制
COPY static /app/static
代码语言:txt
复制
COPY main /app
代码语言:txt
复制
ENV PORT 80 # 设置默认端口号为80,这个值将在容器启动时被覆盖
代码语言:txt
复制
CMD ["/bin/sh", "-c", "./main -p $PORT"]

构建镜像和推送到私有harbor:

代码语言:txt
复制
docker build -t 192.168.11.254:8081/webdemo/goweb:20230515v2 .
代码语言:txt
复制
docker push 192.168.11.254:8081/webdemo/goweb:20230515v2
  1. 测试

<!---->

代码语言:txt
复制
[root@workhost goweb]# docker run --rm -it -p 80:9090 -e PORT=9090 192.168.11.254:8081/webdemo/goweb:20230515v2
代码语言:txt
复制
2023/05/15 02:08:43 ListenAndserve :9090

使用 -p 参数将本地主机的 80 端口映射到容器内部的 9090 端口,使用 -e 参数设置环境变量 PORT 的值为 9090,可以正常启动,说明在启动时已经覆盖掉了默认端口80,且能正常访问:

图片
图片
  1. 创建configmap

<!---->

代码语言:txt
复制
kubectl create configmap goweb --from-literal=port=9091

执行命令后将会创建一个名为 goweb 的 ConfigMap,其中包含一个名为 port 的键,值为 9091。这样,在 Pod 中使用 \$PORT 环境变量时,就可以将其设置为 9091。

说明:--from-literal=port=9091 表示要将 port 这个键的值设置为 9091,这里使用 --from-literal 标志表示将文本作为字面量值创建 ConfigMap。

  1. 创建pod

<!---->

代码语言:txt
复制
apiVersion: v1
代码语言:txt
复制
kind: Pod
代码语言:txt
复制
metadata:
代码语言:txt
复制
  name: goweb
代码语言:txt
复制
spec:
代码语言:txt
复制
  containers:
代码语言:txt
复制
  - name: goweb
    image: 192.168.11.254:8081/webdemo/goweb:20230515v2
    env:
    - name: PORT
      valueFrom:
        configMapKeyRef:
          name: goweb
          key: port

上面yaml中,通过设置 env 字段,将 ConfigMap 中的 port 键值对作为环境变量注入到容器中的应用程序中。使用了 valueFrom 字段指定了 ConfigMap 的名称和键,从而将 ConfigMap 中的 port 值注入到容器的 PORT 环境变量中。这样,在容器启动后,应用程序就可以通过读取 PORT 环境变量的值来获取应该监听的端口,实现了将 ConfigMap 的值注入到容器的环境变量中的功能。

  1. 进入pod验证

<!---->

代码语言:txt
复制
[root@k8s-b-master ~]# kubectl get pod
代码语言:txt
复制
NAME    READY   STATUS    RESTARTS   AGE
代码语言:txt
复制
goweb   1/1     Running   0          29s
代码语言:txt
复制
[root@k8s-b-master ~]# kubectl exec -it goweb -- sh
代码语言:txt
复制
/app # ps
代码语言:txt
复制
PID   USER     TIME  COMMAND
代码语言:txt
复制
    1 root      0:00 ./main -p 9091
代码语言:txt
复制
   11 root      0:00 sh
代码语言:txt
复制
   17 root      0:00 ps
代码语言:txt
复制
/app # 
  1. 完整的yaml

<!---->

代码语言:txt
复制
apiVersion: v1
代码语言:txt
复制
metadata:
代码语言:txt
复制
  name: goweb
代码语言:txt
复制
data:
代码语言:txt
复制
  port: "9091"
代码语言:txt
复制
kind: ConfigMap
代码语言:txt
复制
---
代码语言:txt
复制
apiVersion: apps/v1
代码语言:txt
复制
kind: Deployment
代码语言:txt
复制
metadata:
代码语言:txt
复制
  labels:
代码语言:txt
复制
    app: goweb
代码语言:txt
复制
  name: goweb
代码语言:txt
复制
spec:
代码语言:txt
复制
  replicas: 3
代码语言:txt
复制
  selector:
代码语言:txt
复制
    matchLabels:
代码语言:txt
复制
      app: goweb
代码语言:txt
复制
  template:
代码语言:txt
复制
    metadata:
代码语言:txt
复制
      labels:
代码语言:txt
复制
        app: goweb
代码语言:txt
复制
    spec:
代码语言:txt
复制
      containers:
代码语言:txt
复制
        - name: goweb
          image: 192.168.11.254:8081/webdemo/goweb:20230515v2
          env:
          - name: PORT
            valueFrom:
              configMapKeyRef:
                name: goweb
                key: port

本文转载于WX公众号:不背锅运维:https://mp.weixin.qq.com/s/14zOTnmUSK39PHj8t9m3mQ

本文系转载,前往查看

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

本文系转载前往查看

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 写在开篇
  • 开发示例应用
  • 实战:以使用“容器的环境变量”的方式
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档