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

在使用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

这里写图片描述

需要注意的是: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

这里写图片描述

之后我们可以通过进入同命名空间下的pod中,使用curl进行测试。
就不打了,直接看图。
这里写图片描述

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

配置热更新?

我们验证一下,是否支持配置热更新。
首先我们修改ConfigMap中的内容:
这里写图片描述
上图分别列出了上次修改,以及本次修改后的myConfig的值。

接下来我们再次尝试使用curl请求:
这里写图片描述
上图能够看出,配置并没有热更新。

我们可以通过以下方式,进行强制热更新:
这里写图片描述

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

这种方式的弊端就是:麻烦,以及更新pod后,就变更原pod的环境,名称等等之类的。如下图:
这里写图片描述

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

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

猜你喜欢

转载自blog.csdn.net/ybt_c_index/article/details/80421158