欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

使用Istio Secret/ConfigMap实现外部配置

程序员文章站 2022-06-17 13:03:19
...

在使用spring cloud时,我们知道有对应的config进行配置中心的迁移,将应用配置从应用中剥离出来,放到外部,然后进行统一维护,方便管理;并且config通过使用bus实现了热更新的效果。
那么作为要和spring cloud进行对抗的新一代架构代表Istio,自然也存在类似的功能,不过目前该功能还不完善,无法实现热更新的效果,期待未来会有更好的改进吧。

应用部分

首先我们看一下设计应用的时候,我们需要怎么搞。

@SpringBootApplication
@RestController
public class IstioConfigApplication {

    public static void main(String[] args) {
        SpringApplication.run(IstioConfigApplication.class, args);
    }

    @Value("${MY_SECRET}")
    String secret;

    @Value("${MY_CONFIG}")
    String config;

    @RequestMapping("/secret")
    public String getSecret(){
        return secret;
    }

    @RequestMapping("/config")
    public String getConfig(){
        return config;
    }

}

这是用于测试的主函数,这里我们使用了两个环境变量MY_SECRETMY_CONFIG
再看我们的application文件:

MY_SECRET=""
MY_CONFIG=""
server.port=8848

这里对于MY_SECRETMY_CONFIG这两个环境变量置空了,为什么要做这种多此一举的事呢?
首先我们要知道,当我们使用maven对spring boot应用进行打包的时候,是会启动程序的,如果这时没有对应的环境变量,就无法正常打包;这个对比spring cloud config确实是有很大的不足,但是这是因为spring boot的单方面原因,以及spring对于java的支持过于强大,如果我们使用的是非java语言,可能就不需要多此一举(比如go?)。

总之,后续我们配置ConfigMap/Secret时,是会覆盖之前在application文件中的配置的。

Istio配置

接下来我们看一下在Istio上的几个YAML文件。
首先是创建configMap.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: env-config
  namespace: test-istio
data:
  myConfig: lover~ fucker~

接下来我们再看一看secrets.yaml

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
  namespace: test-istio
type: Opaque
data:
  mySecret: ZG9nd2lu

这块需要稍微解释一下:
Secret主要是用来解决密码、token、**等敏感数据的配置问题,它有三种类型:

  • Service Account :用来访问Kubernetes API,由Kubernetes自动创建,并且会自动挂载到Pod的/run/secrets/kubernetes.io/serviceaccount目录中;
  • Opaque : base64编码格式的Secret,用来存储密码、**等;
  • kubernetes.io/dockerconfigjson :用来存储私有docker registry的认证信息。

而ConfigMap就是主要针对配置文件这块了。

更加详细的信息,请参考jimmysong的kubernetes-handbook

上面的Secret中的base64编码可以在Linux下通过如下命令获取:

$ echo -n <string> | base64

使用Istio Secret/ConfigMap实现外部配置

需要注意的是:base64并不是一种加密手段,它只是一种编码格式,通过解码可以轻易得到原始值。

这时我们已经准备好了对应的ConfigMap/Secret,我们现在需要开始构建Deployment/Service了。

test-config.yaml

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    app: test-config
    version: v1
  name: test-config
spec:
  replicas: 1
  selector:
    matchLabels:
      app: test-config
      version: v1
  template:
    metadata:
      labels:
        app: test-config
        version: v1
    spec:
      containers:
      - image: yubotao/istio-config:test
        imagePullPolicy: IfNotPresent
        name: test-config
        ports:
        - containerPort: 8848
        env:
        - name: MY_SECRET
          valueFrom:
            secretKeyRef:
              name: mysecret
              key: mySecret
        - name: MY_CONFIG
          valueFrom:
            configMapKeyRef:
              name: env-config
              key: myConfig
---

apiVersion: v1
kind: Service
metadata:
  name: test-config
  labels:
    app: test-config
spec:
  ports:
  - name: http
    port: 8848
  selector:
    app: test-config

之后我们执行:

kubectl apply -f <(istioctl kube-inject -f test-config.yaml) -n test-istio

然后看看我们新建的pod是否正常启动了:

kubectl get pods -n test-istio

同时可以通过查看该pod的日志来确认容器启动完成,可以进行测试了:

kubectl logs <podName> -c test-config -n test-istio

使用Istio Secret/ConfigMap实现外部配置

之后我们可以通过进入同命名空间下的pod中,使用curl进行测试。
就不打了,直接看图。
使用Istio Secret/ConfigMap实现外部配置

通过图示,可以看到测试成功。

配置热更新?

我们验证一下,是否支持配置热更新。
首先我们修改ConfigMap中的内容:
使用Istio Secret/ConfigMap实现外部配置
上图分别列出了上次修改,以及本次修改后的myConfig的值。

接下来我们再次尝试使用curl请求:
使用Istio Secret/ConfigMap实现外部配置
上图能够看出,配置并没有热更新。

我们可以通过以下方式,进行强制热更新:
使用Istio Secret/ConfigMap实现外部配置

可以看到,我们通过修改pod的annotation来强制更新pod,进而重启pod中的容器,从而实现了强制配置热更新。

这种方式的弊端就是:麻烦,以及更新pod后,就变更原pod的环境,名称等等之类的。如下图:
使用Istio Secret/ConfigMap实现外部配置

更新的两个pod进行更迭。最后只保留其中一个,也就是上面那个最新创建的。

至此,就告一段落,感觉目前Isito的这个功能对于spring boot的应用来说,比较鸡肋,对于不是特别频繁进行配置更换的应用,完全没必要进行这种配置,不如直接使用application文件。
当然如果频繁更新的话,这种方式还是有一定的好处的,最起码,你不用每次更改配置就发布一个镜像版本。 (囧rz)

相关标签: Istio