kubernetes-加密 Secrets-程序员宅基地

技术标签: 云原生  kubernetes  容器  

1 前言

默认 Secrets 对象的值是 base64 编码的内容,这个可以反编码得到原文的,不能起到加密重要密文的作用。
在这里插入图片描述

解决方法是使用开源的 Sealed Secrets

2 认识 Sealed Secrets

github 地址: https://github.com/bitnami-labs/sealed-secrets

有两部分总成:

  • 集群里的: controller / operator
  • 客户端程序: kubeseal

kubeseal 程序使用非对称加密来加密,只有控制器才能解密。

这些加密的秘密被编码在SealedSecret资源中,您可以将其视为创建秘密的配方。
它的 YAML 资源文件大概是这样的:

apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  name: mysecret
  namespace: mynamespace
spec:
  encryptedData:
    foo: AgBy3i4OJSWK+PiTySYZZA9rO43cGDEq.....

经过 kubernetes 已安装的 controller 解密后相当于下面的内容:

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
  namespace: mynamespace
data:
  foo: YmFy  # <- base64 编码的 "bar"

当这个 SealedSecret 的 secret 被创建的几秒钟之后,它会出现在 kubernetes 中;随后你可以像使用 kubernetes 原生的 secret 一样使用它。例如,从 Pod 引用它。

部署

获取最新的版本 https://github.com/bitnami-labs/sealed-secrets/releases

选择自己喜欢的部署方式即可。
这里选择手动非工具部署

需要下载

  • controller.yml 集群端 控制器
  • kubeseal 客户端程序

controller.yml

---
apiVersion: v1
kind: ServiceAccount
metadata:
  annotations: {
    }
  labels:
    name: sealed-secrets-controller
  name: sealed-secrets-controller
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations: {
    }
  labels:
    name: secrets-unsealer
  name: secrets-unsealer
rules:
- apiGroups:
  - bitnami.com
  resources:
  - sealedsecrets
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - bitnami.com
  resources:
  - sealedsecrets/status
  verbs:
  - update
- apiGroups:
  - ""
  resources:
  - secrets
  verbs:
  - get
  - list
  - create
  - update
  - delete
  - watch
- apiGroups:
  - ""
  resources:
  - events
  verbs:
  - create
  - patch
- apiGroups:
  - ""
  resources:
  - namespaces
  verbs:
  - get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  annotations: {
    }
  labels:
    name: sealed-secrets-controller
  name: sealed-secrets-controller
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: secrets-unsealer
subjects:
- kind: ServiceAccount
  name: sealed-secrets-controller
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  annotations: {
    }
  labels:
    name: sealed-secrets-service-proxier
  name: sealed-secrets-service-proxier
  namespace: kube-system
rules:
- apiGroups:
  - ""
  resourceNames:
  - sealed-secrets-controller
  resources:
  - services
  verbs:
  - get
- apiGroups:
  - ""
  resourceNames:
  - 'http:sealed-secrets-controller:'
  - http:sealed-secrets-controller:http
  - sealed-secrets-controller
  resources:
  - services/proxy
  verbs:
  - create
  - get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  annotations: {
    }
  labels:
    name: sealed-secrets-service-proxier
  name: sealed-secrets-service-proxier
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: sealed-secrets-service-proxier
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: system:authenticated
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  annotations: {
    }
  labels:
    name: sealed-secrets-key-admin
  name: sealed-secrets-key-admin
  namespace: kube-system
rules:
- apiGroups:
  - ""
  resources:
  - secrets
  verbs:
  - create
  - list
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  annotations: {
    }
  labels:
    name: sealed-secrets-controller
  name: sealed-secrets-controller
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: sealed-secrets-key-admin
subjects:
- kind: ServiceAccount
  name: sealed-secrets-controller
  namespace: kube-system
---
apiVersion: v1
kind: Service
metadata:
  annotations: {
    }
  labels:
    name: sealed-secrets-controller
  name: sealed-secrets-controller
  namespace: kube-system
spec:
  ports:
  - port: 8080
    targetPort: 8080
  selector:
    name: sealed-secrets-controller
  type: ClusterIP
---
apiVersion: v1
kind: Service
metadata:
  annotations: {
    }
  labels:
    name: sealed-secrets-controller-metrics
  name: sealed-secrets-controller-metrics
  namespace: kube-system
spec:
  ports:
  - port: 8081
    targetPort: 8081
  selector:
    name: sealed-secrets-controller
  type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations: {
    }
  labels:
    name: sealed-secrets-controller
  name: sealed-secrets-controller
  namespace: kube-system
spec:
  minReadySeconds: 30
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      name: sealed-secrets-controller
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      annotations: {
    }
      labels:
        name: sealed-secrets-controller
    spec:
      containers:
      - args: []
        command:
        - controller
        env: []
        image: docker.io/bitnami/sealed-secrets-controller:0.26.1
        imagePullPolicy: IfNotPresent
        livenessProbe:
          httpGet:
            path: /healthz
            port: http
        name: sealed-secrets-controller
        ports:
        - containerPort: 8080
          name: http
        - containerPort: 8081
          name: metrics
        readinessProbe:
          httpGet:
            path: /healthz
            port: http
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop:
            - ALL
          readOnlyRootFilesystem: true
        stdin: false
        tty: false
        volumeMounts:
        - mountPath: /tmp
          name: tmp
      imagePullSecrets: []
      securityContext:
        fsGroup: 65534
        runAsNonRoot: true
        runAsUser: 1001
        seccompProfile:
          type: RuntimeDefault
      serviceAccountName: sealed-secrets-controller
      terminationGracePeriodSeconds: 30
      volumes:
      - emptyDir: {
    }
        name: tmp
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: sealedsecrets.bitnami.com
spec:
  group: bitnami.com
  names:
    kind: SealedSecret
    listKind: SealedSecretList
    plural: sealedsecrets
    singular: sealedsecret
  scope: Namespaced
  versions:
  - name: v1alpha1
    schema:
      openAPIV3Schema:
        description: SealedSecret is the K8s representation of a "sealed Secret" -
          a regular k8s Secret that has been sealed (encrypted) using the controller's
          key.
        properties:
          apiVersion:
            description: 'APIVersion defines the versioned schema of this representation
              of an object. Servers should convert recognized schemas to the latest
              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
            type: string
          kind:
            description: 'Kind is a string value representing the REST resource this
              object represents. Servers may infer this from the endpoint the client
              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
            type: string
          metadata:
            type: object
          spec:
            description: SealedSecretSpec is the specification of a SealedSecret
            properties:
              data:
                description: Data is deprecated and will be removed eventually. Use
                  per-value EncryptedData instead.
                format: byte
                type: string
              encryptedData:
                additionalProperties:
                  type: string
                type: object
                x-kubernetes-preserve-unknown-fields: true
              template:
                description: Template defines the structure of the Secret that will
                  be created from this sealed secret.
                properties:
                  data:
                    additionalProperties:
                      type: string
                    description: Keys that should be templated using decrypted data
                    nullable: true
                    type: object
                  immutable:
                    description: Immutable, if set to true, ensures that data stored
                      in the Secret cannot be updated (only object metadata can be
                      modified). If not set to true, the field can be modified at
                      any time. Defaulted to nil.
                    type: boolean
                  metadata:
                    description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata'
                    nullable: true
                    properties:
                      annotations:
                        additionalProperties:
                          type: string
                        type: object
                      finalizers:
                        items:
                          type: string
                        type: array
                      labels:
                        additionalProperties:
                          type: string
                        type: object
                      name:
                        type: string
                      namespace:
                        type: string
                    type: object
                    x-kubernetes-preserve-unknown-fields: true
                  type:
                    description: Used to facilitate programmatic handling of secret
                      data.
                    type: string
                type: object
            required:
            - encryptedData
            type: object
          status:
            description: SealedSecretStatus is the most recently observed status of
              the SealedSecret.
            properties:
              conditions:
                description: Represents the latest available observations of a sealed
                  secret's current state.
                items:
                  description: SealedSecretCondition describes the state of a sealed
                    secret at a certain point.
                  properties:
                    lastTransitionTime:
                      description: Last time the condition transitioned from one status
                        to another.
                      format: date-time
                      type: string
                    lastUpdateTime:
                      description: The last time this condition was updated.
                      format: date-time
                      type: string
                    message:
                      description: A human readable message indicating details about
                        the transition.
                      type: string
                    reason:
                      description: The reason for the condition's last transition.
                      type: string
                    status:
                      description: 'Status of the condition for a sealed secret. Valid
                        values for "Synced": "True", "False", or "Unknown".'
                      type: string
                    type:
                      description: 'Type of condition for a sealed secret. Valid value:
                        "Synced"'
                      type: string
                  required:
                  - status
                  - type
                  type: object
                type: array
              observedGeneration:
                description: ObservedGeneration reflects the generation most recently
                  observed by the sealed-secrets controller.
                format: int64
                type: integer
            type: object
        required:
        - spec
        type: object
    served: true
    storage: true
    subresources:
      status: {
    }

基本使用

以某种方式创建一个json/yaml编码的Secret:

echo -n bar | kubectl create secret generic mysecret --dry-run=client --from-file=foo=/dev/stdin -o yaml >mysecret.yml

内容如下:

apiVersion: v1
data:
  foo: YmFy
kind: Secret
metadata:
  creationTimestamp: null
  name: mysecret

生成加密的 secret 资源文件

kubeseal -f mysecret.yml -w mysealedsecret.yml

数据被加密后的资源文件如下:

---
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  creationTimestamp: null
  name: mysecret
  namespace: default
spec:
  encryptedData:
    foo: AgA4KaUIHoNRNv8ZN1H1+dZfRyHFahVcTMMgRjoTkbL8dYmImstmw9oxrahaL8OOji5inMZ+AYP2UGJjUzflWN5SNOWpFGLN5LGHG2tinp1TWt14wCI20XqbVkGsbEwiQeh8Nudb32EgCJ0/Z4dYsa3zBR1jAbklyNv3s8sUnvDN/yvijMJYqxU3kbnHqQhiwt9SohTw445GCv1YlOe7ZqmB1MR2uK+3tRx7WUWpGe8A84uxZEJYMps/S5gxbGUMp5uvIm55S3fEYsWxqus6ssVMUoBAyCaVKCkftfRQBBd2bpBTiiQ8cnAw2BRVaGtDCHKqbZ/FY/uhllUOHxfQxzWwtDh1k3hQgXLnvG8krJytZ4OqZmkWYsOYPgakwZcZeLpBryEJv5CuwG/5RCOM5Cxjlwqph2Kfah0kULNdoAe4GbwvW1bK0PI/9SKZbrhiQ/o6GfR30W9aos3ucNbZihRA9P6er8sWbguzN3qYvdqbrSdrJ+VAyjty7lEBR/BTlUo5NdjbLuYTOhGbhcvCi7TYXThklRjisNzbS1pd/CMIm8difwEudnXmx44+hsqoK8MLgYXXEdSriJuHMeql881pxP2HQjXabr4MJkTKO7hznc4/vNnP+QtNbvjL01f1XDxIUrzsv1D3T45pBYYIfvJGb9rcskyunjJvhyJ2LUAlWY6f3uKUTwBwSIcoEX4V6WuuKYc=
  template:
    metadata:
      creationTimestamp: null
      name: mysecret
      namespace: default

创建资源对象到集群中

kubectl apply -f mysealedsecret.yml

查看资源对象

kubectl get secret mysecret

输出如下内容:

NAME       TYPE     DATA   AGE
mysecret   Opaque   1      17m

查看对象详情

 kubectl describe secret mysecret

输出如下内容:

Name:         mysecret
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
foo:  3 bytes

请注意,SealedSecret 和 Secret 必须具有相同的命名空间和名称。这是一个防止同一集群上的其他用户重新使用您的密封机密的功能。

在 Pod 中使用
busybox.yml 文件内容:

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: mypod
      image: busybox
      command:
        - cat
        - "/etc/mysecret/foo"
      volumeMounts:
        - name: foo
          mountPath: "/etc/mysecret"
          readOnly: true
  volumes:
    - name: foo
      secret:
        secretName: mysecret

创建这个 Pod:

kubectl apply -f busybox.yml

在这里插入图片描述
这个 SealedSecret对象的创建不验证用户。换句话说,任何人都可以创建一个Sealed Secret 对象。
这个和原生的 Secret 对象是一样的设计,都是通过集群的 RBAC 机制控制使用的权限。

管理现有的 Secret

如果希望 Sealed Secrets 控制器管理现有的 Secret,您可以使用 Sealed Secret 对您的 Secret 添加 sealedsecrets.bitnami.com/managed: "true" annotations(注解)。
当解封具有相同名称和命名空间的 Sealed Secret 时,现有的 Secret 将被覆盖,并且 Sealed Secrets 将拥有该 Secret 的所有权(因此,当删除 Sealed Secret 时,该 Secret 也将被删除)。

例如有一个现有的 Secret 对象 test-secret, 他的 YAML 文件内容如下:

apiVersion: v1
kind: Secret
metadata:
  name: testsecret
data:
  foo: MTIz

给原有的 Secret 添加注释

apiVersion: v1
kind: Secret
metadata:
  name: testsecret
  annotations:
    sealedsecrets.bitnami.com/managed: "true"
data:
  foo: MTIz

应用一下

kubectl apply -f test-seal.yml

查看运行中的 testsecret 对象的信息
在这里插入图片描述
查看运行中的 testsecret 对象 YAML 内容
在这里插入图片描述

接着,我创建同名的 Sealed Secrets 对象

这里我偷懒了,没通过创建新的密码创建 Sealed Secrets 对象,而是沿用原来的 Secrets 对象中的密码。
正确的做法是使用新的密码创建 Sealed Secrets 对象去覆盖原来的 Secrets 对象。

kubeseal -f test-secret.yml -w test-seal.yml

kubectl  apply -f test-seal.yml

后面就可以使用这个含有加密秘密内容的 YAML 文件 test-seal.yml ,给到 开发使用了,即使可以查看文件中的内容,但因为里面的敏感数据已经被加密,真正的密码也可以得到有效的保护。

并且,此时再查看 Secret 实力对象 testsecret,会发现对象已经被覆盖。
在这里插入图片描述
在这里插入图片描述

如果此时,删除 Sealed Secret 对象, 对应的这个 Secret 实例对象 testsecret 也会被删除。
在这里插入图片描述

验证密文的有效性

加入你得到一个有加密密文的 YAML 文件

---
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  creationTimestamp: null
  name: testsecret
  namespace: default
spec:
  encryptedData:
    foo: AgAK7TTRNORyvO6nQFq9w0Unj6e+/NHPyipdtbuwdfhyvnZavLpmUIcbHnj/wj/QFvbFiAtc2NoTG2g/sZIZJ8/ZgJi4a7lrNJbCFKcSdxDSyPcAdP0K9SjiSqcpFxw1zVw0NJOtV2q8khcY+aDkk7QWdxio8+0qdSpb5KvbB+eCAByxVdixHJXd8Ul2s/6CqRCkm3DGwwvvvV/1ogoUWMidaZXK/Ju4RopAaKYrnJ0fSpDrR8vRZEC6wJD6HRXc5cXeVXJ8g3SXgAQ1tjRuJkBxF+5S8jODihioBVLbq++6FxXJ/4bepy7NFcY/K7ldnp/B6xngqFiawYuUlPnI+iscE6YkSlSFFGohrgj6xByGVf7jCNBbbOY9itgu8AY/zrAUCedgr8c+xtPfX7cwGlGicD5sw/M1mpRXE0T6uH3H3MTazHk2KZvXTk290pOF6bYrzoV5AsG6I37+fAhDDJs1WFtj47kk0eaiwKJuSPeSVxlQyKqP50oemhK3aXJCOz6ryZUppSD8ufRRqGJls+lN8oFLZakfR6sjYY5zQFLaHIw5vo9egn7dSdUdKch3lP5D4pSohSdHrSYJnEplA4XImRu68X5phJyih6IWPRrOtDv4wZ9+B3qSVMTD5YdyEPirt4azb6pY7Xk4NvCDQctgWP4FRzdjVzu2FNru6t8cC+Gz7fwIJXMr1dkH4W/e8I4UldU=
  template:
    metadata:
      creationTimestamp: null
      name: testsecret
      namespace: default

如果你想验证文件内的加密密文是否有效,或者是否得到破坏。可以使用如下命令验证

cat test-seal.yml | kubeseal --validate

如果正常,则没有任何返回。如果有问题,则会返回如下内容:

error: unable to decrypt sealed secret: testsecret

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_22648091/article/details/137140137

智能推荐

Kyligence 发布数据和分析领域垂直大模型司南(Compass)_司南模型怎么测试-程序员宅基地

文章浏览阅读140次。12 月 19 日,跬智信息(Kyligence)正式发布数据和分析领域垂直大模型司南(Compass)(以下简称“司南大模型”)。基于多年数据和分析领域的实践积累和全行业指标洞察的海量语料,Kyligence司南大模型已具备自然语言对话分析、指标搜索与推荐、自动化数据洞察、KPI 评估、智能决策建议等核心能力。_司南模型怎么测试

MySQL数据库Insert语句慢SQL处理-程序员宅基地

文章浏览阅读3.8k次。#问题描述insert into …普通的插入语句,经常出现耗时2s以上#数据状态1.表数据量大,每天产生200万条数据2.高并发插入#问题解决1.由于表中数据量庞大,建议数据归档处理,冷热处理2.表中有过多索引,当数据insert时,索引会重排产生太多的io操作。导致缓慢,有必然要的只保留主键。3.表的数据库引擎,默认InnerDB,若数据不重要,可以使用MyISAM......

EasyDarwin开源流媒体云平台之EasyRMS录播服务器功能设计_开源录播系统-程序员宅基地

文章浏览阅读3.6k次。需求背景EasyDarwin开发团队维护EasyDarwin开源流媒体服务器也已经很多年了,之前也陆陆续续尝试过很多种服务端录像的方案,有:在EasyDarwin中直接解析收到的RTP包,重新组包录像;也有:在EasyDarwin中新增一个RecordModule,再以RTSPClient的方式请求127.0.0.1自己的直播流录像,但这些始终都没有成气候;我们的想法是能够让整套EasyDarwin_开源录播系统

oracle Plsql 执行update或者delete时卡死问题解决办法_oracle delete update 锁表问题-程序员宅基地

文章浏览阅读1.1w次。今天碰到一个执行语句等了半天没有执行:delete table XXX where ......,但是在select 的时候没问题。后来发现是在执行select * from XXX for update 的时候没有commit,oracle将该记录锁住了。可以通过以下办法解决: 先查询锁定记录 Sql代码 SELECT s.sid, s.seri_oracle delete update 锁表问题

Xcode Undefined symbols 错误_xcode undefined symbols:-程序员宅基地

文章浏览阅读3.4k次。报错信息error:Undefined symbol: typeinfo for sdk::IConfigUndefined symbol: vtable for sdk::IConfig具体信息:Undefined symbols for architecture x86_64: "typeinfo for sdk::IConfig", referenced from: typeinfo for sdk::ConfigImpl in sdk.a(config_impl.o) _xcode undefined symbols:

项目05(Mysql升级07Mysql5.7.32升级到Mysql8.0.22)_mysql8.0.26 升级32-程序员宅基地

文章浏览阅读249次。背景《承接上文,项目05(Mysql升级06Mysql5.6.51升级到Mysql5.7.32)》,写在前面需要(考虑)检查和测试的层面很多,不限于以下内容。参考文档https://dev.mysql.com/doc/refman/8.0/en/upgrade-prerequisites.htmllink推荐阅读以上链接,因为对应以下问题,有详细的建议。官方文档:不得存在以下问题:0.不得有使用过时数据类型或功能的表。不支持就地升级到MySQL 8.0,如果表包含在预5.6.4格_mysql8.0.26 升级32

随便推点

改变Android Studio的背景background_as怎么设置背景-程序员宅基地

文章浏览阅读2.7k次,点赞2次,收藏5次。改变Android Studio的背景background我们先点File然后再点Settings里的Appearance,点击Theme换成Darcula 把白色换成黑色,这样的好处是换成background是图片比较清晰。此处正式开始AS换背景这里我们颜色从白色换成了黑色,先点File里Settings的Appearance然后点background image把你喜欢的图片放进去(图片放在D盘自己新建的文件)..._as怎么设置背景

桩筏有限元中的弹性板计算_专栏 l 增材制造点阵结构在压力容器优化设计中的应用...-程序员宅基地

文章浏览阅读179次。“增材制造是未来制造业的发展趋势,其优势显而易见,它可以实现传统加工工艺难以制造的设计,比如复杂薄壁结构、点阵结构、一体化结构等。其中,点阵结构作为一种新型的轻量化结构,具有良好的比刚度、比强度等力学性能。传统加工工艺很难制造点阵结构,3D打印技术的快速发展使得点阵结构的制造更加具有可行性。”本期谷.专栏列举了面向增材制造的点阵加筋一体化压力容器的设计与分析案例,仿真技术作为正向设计体系..._点阵结构的等效属性计算

Firefox安装广告屏蔽插件(uBlock Origin)_ublock origin插件-程序员宅基地

文章浏览阅读5.9k次,点赞2次,收藏2次。由于国内用户IP被屏蔽的原因,安装广告屏蔽插件(uBlock Origin、AdGuard、AdBlocker、AdBlock For Firefox、AdBlock)访问受限,官方原因为“由于法律原因不可用(HTTP 451 Unavailable For Legal Reasons)”,需要另辟蹊径安装,以下是安装uBlock Origin的方法介绍。然后,在Firefox的扩展管理页面,打开【从文件安装附加组件】选项。选择刚才下载的.xpi文件,就可以成功安装了。_ublock origin插件

k8s挂载目录_kubernetes(k8s)的pod使用统一的配置文件configmap挂载-程序员宅基地

文章浏览阅读1.2k次。在容器化应用中,每个环境都要独立的打一个镜像再给镜像一个特有的tag,这很麻烦,这就要用到k8s原生的配置中心configMap就是用解决这个问题的。使用configMap部署应用。这里使用nginx来做示例,简单粗暴。直接用vim常见nginx的配置文件,用命令导入进去kubectl create cm nginx.conf --from-file=/home/nginx.conf然后查看kub..._pod mount目录会自动创建吗

java计算机毕业设计springcloud+vue基于微服务的分布式新生报到系统_关于spring cloud的参考文献有啥-程序员宅基地

文章浏览阅读169次。随着互联网技术的发发展,计算机技术广泛应用在人们的生活中,逐渐成为日常工作、生活不可或缺的工具,高校各种管理系统层出不穷。高校作为学习知识和技术的高等学府,信息技术更加的成熟,为新生报到管理开发必要的系统,能够有效的提升管理效率。一直以来,新生报到一直没有进行系统化的管理,学生无法准确查询学院信息,高校也无法记录新生报名情况,由此提出开发基于微服务的分布式新生报到系统,管理报名信息,学生可以在线查询报名状态,节省时间,提高效率。_关于spring cloud的参考文献有啥

VB.net学习笔记(十五)继承与多接口练习_vb.net 继承多个接口-程序员宅基地

文章浏览阅读3.2k次。Public MustInherit Class Contact '只能作基类且不能实例化 Private mID As Guid = Guid.NewGuid Private mName As String Public Property ID() As Guid Get Return mID End Get_vb.net 继承多个接口