Управление кластером контейнеров Docker / Rocket (или чего-либо еще) в производственной среде сопряжено с проблемами распределенных систем. К счастью, убедительное и очень энергичное сообщество вокруг проекта Kubernetes работает над этими проблемами, используя многолетний опыт работы в Google, Red Hat и стартапах, чтобы помочь другим. Если вы еще не пробовали Kubernetes для управления вашими контейнерами Docker, вам стоит заняться этим!
В сообществе Fabric8 мы работаем над опытом разработчиков на платформах Kubernetes и Enterprise Kubernetes / OpenShift, а также на их основе. У нас есть отличная веб-консоль для управления кластером Kubernetes, наборы библиотек для взаимодействия с кластером, в том числе клиент kubernetes с безопасным типом DSL, встроенная поддержка CI / CD одним щелчком с помощью Jenkins Workflow , Helm .sh упаковка приложений, управление API, Chaos Monkey и многие другие вкусности. Проверьте сайт fabric8.io для получения дополнительной информации. Может показаться, что Fabric8 имеет наклон JVM высокого уровня, но он не специфичен для Java и может применяться к golang / node / python / any Language. Пожалуйста, не стесняйтесь присоединиться и внести свой вклад!
Одна из проблем, с которой я столкнулся при работе с клиентами, использующими Kubernetes / OpenShift, заключается в том, что на данный момент нет хороших инструментов для создания файлов манифеста JSON / YAML Kubernetes или для настройки существующих файлов манифеста. JSON (и даже YAML) очень подвержены ошибкам при ручном редактировании, поэтому нам нужно что-то лучшее.
Если вы разработчик Java / JVM, вам повезло. Сообщество fabric8 имеет удивительный DSL для автоматической генерации файлов манифеста Kubernetes .
Вот пример того, как выглядит свободный конструктор API:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
@KubernetesProviderpublic KubernetesList create() { return new KubernetesListBuilder() .addNewReplicationControllerItem() .withNewMetadata() .withName("Hello-Controller") .endMetadata() .withNewSpec() .withReplicas(1) .addToSelector("component", "my-component") .withNewTemplate() .withNewSpec() .addNewContainer() .withName("my-container") .withImage("my/image") .endContainer() .endSpec() .endTemplate() .endSpec() .endReplicationControllerItem() .build(); |
В этом блоге мы рассмотрим его мощь — и то, как в сочетании с плагином fabric8 maven — управление и взаимодействие с API Kubernetes через файлы манифеста Kubernetes намного приятнее. Цель состоит в том, чтобы быть практическим, так что не стесняйтесь следовать, или, если вы спешите, чтобы увидеть примеры, найдите образец репозитория github
Создать новый проект
У Fabric8 есть множество быстрых стартов и архетипов mvn, чтобы вы начали. Мы начнем с создания проекта из проекта maven, из которого мы можем продемонстрировать kubernetes typesafe dsl:
mvn архетип: генерировать -DarchetypeGroupId = io.fabric8.archetypes -DarchetypeArtifactId = vertx-simplest-archetype -DarchetypeVersion = 2.2.93
Следуйте интерактивной подсказке, чтобы заполнить groupId / artifactId и т. Д. Затем убедитесь, что проект может быть mvn clean install
После того, как вы выполнили сборку mvn, вы должны увидеть в каталоге target/classes что были сгенерированы файлы kubernetes.json и kubernetes.yml . Взгляните на файл kubernetes.json:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
{ "apiVersion" : "v1", "items" : [ { "apiVersion" : "v1", "kind" : "Service", "metadata" : { "annotations" : { }, "labels" : { "container" : "java", "component" : "typesafe-kubernetes-dsl", "provider" : "fabric8", "project" : "typesafe-kubernetes-dsl", "version" : "1.0-SNAPSHOT", "group" : "quickstarts" }, "name" : "typesafe-kubernetes-dsl" }, "spec" : { "deprecatedPublicIPs" : [ ], "externalIPs" : [ ], "ports" : [ { "port" : 80, "protocol" : "TCP", "targetPort" : 8080 } ], "selector" : { "container" : "java", "project" : "typesafe-kubernetes-dsl", "component" : "typesafe-kubernetes-dsl", "provider" : "fabric8", "group" : "quickstarts" }, "type" : "LoadBalancer" } }, { "apiVersion" : "v1", "kind" : "ReplicationController", "metadata" : { "annotations" : { }, "labels" : { "container" : "java", "component" : "typesafe-kubernetes-dsl", "provider" : "fabric8", "project" : "typesafe-kubernetes-dsl", "version" : "1.0-SNAPSHOT", "group" : "quickstarts" }, "name" : "typesafe-kubernetes-dsl" }, "spec" : { "replicas" : 1, "selector" : { "container" : "java", "component" : "typesafe-kubernetes-dsl", "provider" : "fabric8", "project" : "typesafe-kubernetes-dsl", "version" : "1.0-SNAPSHOT", "group" : "quickstarts" }, "template" : { "metadata" : { "annotations" : { }, "labels" : { "container" : "java", "component" : "typesafe-kubernetes-dsl", "provider" : "fabric8", "project" : "typesafe-kubernetes-dsl", "version" : "1.0-SNAPSHOT", "group" : "quickstarts" } }, "spec" : { "containers" : [ { "args" : [ ], "command" : [ ], "env" : [ { "name" : "KUBERNETES_NAMESPACE", "valueFrom" : { "fieldRef" : { "fieldPath" : "metadata.namespace" } } } ], "image" : "fabric8/typesafe-kubernetes-dsl:1.0-SNAPSHOT", "name" : "typesafe-kubernetes-dsl", "ports" : [ ], "securityContext" : { }, "volumeMounts" : [ ] } ], "imagePullSecrets" : [ ], "nodeSelector" : { }, "volumes" : [ ] } } } } ], "kind" : "List" } |
Как это случилось?
fabric8-Maven-плагин
Первый вариант для безопасного для типов объявления без json ваших объектов Kubernetes — это использование конфигурации для fabric8-maven-plugin через свойства mvn. Если вы посмотрите в раздел <properties/> файла maven pom.xml, вы увидите некоторую конфигурацию, которую использует плагин fabric8-maven-plugin для автоматической генерации kubernetes.json:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
<!-- Docker & Fabric8 Configs --> <docker.from>fabric8/java-jboss-openjdk8-jdk:1.0.10</docker.from> <fabric8.dockerUser>fabric8/</fabric8.dockerUser> <docker.image>${fabric8.dockerUser}${project.artifactId}:${project.version}</docker.image> <fabric8.label.component>${project.artifactId}</fabric8.label.component> <fabric8.label.container>java</fabric8.label.container> <fabric8.label.group>quickstarts</fabric8.label.group> <fabric8.iconRef>vertx</fabric8.iconRef> <fabric8.service.name>${project.artifactId}</fabric8.service.name> <fabric8.service.port>80</fabric8.service.port> <fabric8.service.containerPort>8080</fabric8.service.containerPort> <fabric8.service.type>LoadBalancer</fabric8.service.type> |
Ура! Простые свойства, которые нужно заполнить, чтобы получить наш kubernetes manfiest, и это (и все значения) являются частью manfiest! Вы также можете указать переменные окружения и свойства шаблона OpenShift для плагина maven через свойства. Посмотрите документы для получения дополнительной информации об этом и конкретных свойствах, которые вы можете использовать для настройки генерации файлов манифеста.
Однако вы можете заметить, что только наиболее часто используемые конструкции (службы, контроллер репликации, … и учетные записи служб) имеют полезные свойства в подключаемом модуле maven. Это должно получить около 80%. Но что, если мы хотим добавить / настроить файл kubernetes.json, сгенерированный как часть этого плагина mvn? Или что, если у нас есть собственный файл kubernetes.json, который мы создали вручную, но хотим, чтобы редактирование было безопасным для типов? Или что, если мы просто хотим сгенерировать его на 100% с нуля, используя безопасный тип?
Тип безопасной DSL
Мы можем сделать это с помощью kubernetes-generator kubernetes из fabric8.io, которая в основном является фабрикой процессоров аннотаций Java, которую мы используем для генерации / дополнения файлов kubernetes.json / yml. (Обратите внимание, что для генерации yml и указания явных имен файлов вам нужно будет использовать fabric8 версии 2.2.89 или выше, в противном случае применяется предположение json и имя файла kubernetes.json).
Добавьте следующее в ваш maven pom.xml
|
1
2
3
4
|
<dependency> <groupId>io.fabric8</groupId> <artifactId>kubernetes-generator</artifactId> </dependency> |
Допустим, в этом примере мы хотим добавить сведения о постоянном томе в наши файлы Kubernetes.json / yml. Ключом к этому является простое создание POJO и аннотирование его с помощью @KubernetesModelProcessor следующим образом:
|
1
2
3
4
|
@KubernetesModelProcessorpublic class PersistentVolumeKubernetesModelProcessor { } |
Теперь в этом новом классе мы можем изменять или добавлять новые компоненты в файлы kubernetes.json / yml. Мы делаем это, следуя шаблону «посетитель». Подумайте, будет ли это, когда мы перебираем объекты в файле manfiest из Kubernetes, и предложим их вашим методам, чтобы вы могли работать по своему усмотрению. На самом деле, хотя это то, что происходит в фоновом режиме, вы не подделаны, чтобы иметь дело с каждым объектом в манифесте Kubernetes, если вы не хотите; вы просто работаете над / расширяете / увеличиваете интересующие вас объекты. Вы делаете это, определяя параметры ваших методов, чтобы брать определенные типы объектов (то есть, объекты, которые вас интересуют). Например, если ваш список ресурсов имеет ReplicationController, и вы хотите добавить больше модулей в его спецификацию шаблона, вы бы объявили свой метод следующим образом:
|
1
2
3
|
public void on(ReplicationControllerSpecBuilder builder) { } |
Обратите внимание на тип параметра. Таким образом, мы можем выбрать только те части модели, над которыми мы хотим работать. Точно так же, если вы хотите только PodSpec:
|
1
2
3
|
public void on(PodSpecBuilder builder) { } |
Некоторые полезные объекты-строители:
- KubernetesListBuilder
- ReplicationControllerBuilder
- ReplicationControllerSpecBuilder
- PodSpecBuilder
- ServiceSpecBuilder
- IngressRuleBuilder
- PersistentVolumeBuilder
- DaemonSetBuilder
Некоторые полезные объекты-сборщики для OpenShift:
- TemplateBuilder
- RouteBuilder
- OAuthAccessTaskBuilder
- OAuthClientBuilder
- ProjectBuilder
- DeploymentStrategyBuilder
В нашем примере проекта мы будем использовать следующую реализацию для добавления набора постоянных томов, утверждений и монтирования в наш существующий ресурс манифеста kubernetes:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
public void on(KubernetesListBuilder builder){ builder.addNewPersistentVolumeClaimItem() .withNewMetadata() .withName("typesafe-dsl-pv") .addToLabels("provider", "fabric8") .addToLabels("project", "typesafe-dsl") .addToLabels("group", "demo") .endMetadata() .withNewSpec() .withAccessModes("ReadWriteOnce") .withResources(getResourceRequirement()) .endSpec() .endPersistentVolumeClaimItem() .build(); } |
Обратите внимание на то, как беглый DSL соединяется вместе, используя структуру предложения (предметно-ориентированный язык). В приведенном выше фрагменте мы «заходим в KubernetesListBuilder и добавляем новый объект PersistentVolumeClaim и указываем метки, режимы доступа и ресурсы (см. Полный исходный код для того, как мы вычисляем ресурс).
Теперь нам нужно добавить настройки монтирования тома / тома в наш манифест kubernetes. Для существующих ресурсов мы отредактируем существующие описания ресурсов, как это (и мы также выберем определенный ContainerBuilder по имени!)
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
public void withPodTemplate(PodTemplateSpecBuilder builder) { builder.withSpec(builder.getSpec()) .editSpec() .addNewVolume() .withName("typesafe-kubernetes-dsl-volume") .withPersistentVolumeClaim(getPersistentVolumeClaimSource()) .endVolume() .endSpec() .build(); } private PersistentVolumeClaimVolumeSource getPersistentVolumeClaimSource() { PersistentVolumeClaimVolumeSource rc = new PersistentVolumeClaimVolumeSource("typesafe-kubernetes-dsl-pvc", false); return rc; } @Named("typesafe-kubernetes-dsl") public void withVolumeMounts(ContainerBuilder builder) { builder.withVolumeMounts(new VolumeMount("/deployments/target/placeorder", "typesafe-kubernetes-dsl-volume", false)) .build(); } } |
Теперь, когда вы выполняете чистую установку mvn, вы должны увидеть, что kubernetes.json / yml был корректно изменен с добавлением постоянного тома, монтирования тома и т. Д. Довольно гладкий DSL, да?
Генерация Kubernetes DSL с нуля
Вы также можете использовать этот безопасный DSL для создания JSON / YML для Kubernetes. Это было бы полезно, если вы не хотите использовать плагины mvn (т.е. вы используете gradle, sbt или что-то еще). Для этого мы аннотируем методы с помощью @KubernetesProvider и используем те же объекты компоновщика, что и раньше. Например, в нашем вышеупомянутом проекте мы создали постоянные заявки на объем и добавили их в наши файлы манифеста kubernetes. Пользователи смогут применять их к своим проектам, но пользователи обычно не управляют резервной копией PersistentVolumes, это может сделать администратор сборки / выпуска или кластера / проекта. Поэтому имеет смысл выделить метаданные PersistentVolume в собственный файл манифеста и доставить его отдельно.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
@KubernetesProvider("typesafe-kubernetes-dsl-pv.yml") public KubernetesList buildList() { return new KubernetesListBuilder().addNewPersistentVolumeItem() .withNewMetadata() .withName("typesafe-kubernetes-dsl-pv") .addToLabels("provider", "fabric8") .addToLabels("project", "typesafe-kubernetes-dsl") .addToLabels("group", "demo") .endMetadata() .withNewSpec() .addToCapacity("storage", new Quantity("100Ki")) .addToAccessModes("ReadWriteOnce") .withHostPath(new HostPathVolumeSource("/home/vagrant/camel")) .endSpec() .endPersistentVolumeItem() .build(); } |
Теперь, когда вы запускаете сборку maven, вы должны увидеть kubernetes.json / yaml, а также typesafe-kubernetes-dsl-pv.yml, в котором будет наш YAML-файл для PersistentVolume.
Пожалуйста, ознакомьтесь с типом безопасной обработки аннотации DSL Fabric8 и примером проекта, чтобы согласиться с этим сообщением в блоге . Хотелось бы получить ваши отзывы @ fabric8io или @christianposta
| Ссылка: | Typesafe Kubernetes-манифест DSL для приложений на основе JVM от нашего партнера JCG Кристиана Поста в блоге |