mirror of
https://github.com/kubesphere/kubekey.git
synced 2025-12-25 17:12:50 +00:00
feat: install image_registry (#2640)
Signed-off-by: joyceliu <joyceliu@yunify.com>
This commit is contained in:
parent
9686e047be
commit
8237a2fd88
|
|
@ -14,7 +14,7 @@ spec:
|
|||
etcd_version: v3.5.4
|
||||
# ========== image registry ==========
|
||||
# keepalived image tag. Used for load balancing when there are multiple image registry nodes.
|
||||
# keepalived_version: stable
|
||||
# keepalived_version: 2.0.20
|
||||
# ========== image registry: harbor ==========
|
||||
# harbor image tag
|
||||
# harbor_version: v2.6.3
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ spec:
|
|||
etcd_version: v3.5.6
|
||||
# ========== image registry ==========
|
||||
# keepalived image tag. Used for load balancing when there are multiple image registry nodes.
|
||||
# keepalived_version: stable
|
||||
# keepalived_version: v2.0.20
|
||||
# ========== image registry: harbor ==========
|
||||
# harbor image tag
|
||||
# harbor_version: v2.7.1
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ spec:
|
|||
etcd_version: v3.5.7
|
||||
# ========== image registry ==========
|
||||
# keepalived image tag. Used for load balancing when there are multiple image registry nodes.
|
||||
# keepalived_version: stable
|
||||
# keepalived_version: 2.0.20
|
||||
# ========== image registry: harbor ==========
|
||||
# harbor image tag
|
||||
# harbor_version: v2.8.1
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ spec:
|
|||
etcd_version: v3.5.8
|
||||
# ========== image registry ==========
|
||||
# keepalived image tag. Used for load balancing when there are multiple image registry nodes.
|
||||
# keepalived_version: stable
|
||||
# keepalived_version: 2.0.20
|
||||
# ========== image registry: harbor ==========
|
||||
# harbor image tag
|
||||
# harbor_version: v2.9.1
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ spec:
|
|||
etcd_version: v3.5.9
|
||||
# ========== image registry ==========
|
||||
# keepalived image tag. Used for load balancing when there are multiple image registry nodes.
|
||||
# keepalived_version: stable
|
||||
# keepalived_version: 2.0.20
|
||||
# ========== image registry: harbor ==========
|
||||
# harbor image tag
|
||||
# harbor_version: v2.10.1
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ spec:
|
|||
etcd_version: v3.5.9
|
||||
# ========== image registry ==========
|
||||
# keepalived image tag. Used for load balancing when there are multiple image registry nodes.
|
||||
# keepalived_version: stable
|
||||
# keepalived_version: 2.0.20
|
||||
# ========== image registry: harbor ==========
|
||||
# harbor image tag
|
||||
# harbor_version: v2.10.1
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ spec:
|
|||
etcd_version: v3.5.10
|
||||
# ========== image registry ==========
|
||||
# keepalived image tag. Used for load balancing when there are multiple image registry nodes.
|
||||
# keepalived_version: stable
|
||||
# keepalived_version: 2.0.20
|
||||
# ========== image registry: harbor ==========
|
||||
# harbor image tag
|
||||
# harbor_version: v2.10.1
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ spec:
|
|||
etcd_version: v3.5.10
|
||||
# ========== image registry ==========
|
||||
# keepalived image tag. Used for load balancing when there are multiple image registry nodes.
|
||||
# keepalived_version: stable
|
||||
# keepalived_version: 2.0.20
|
||||
# ========== image registry: harbor ==========
|
||||
# harbor image tag
|
||||
# harbor_version: v2.10.1
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ spec:
|
|||
etcd_version: v3.5.11
|
||||
# ========== image registry ==========
|
||||
# keepalived image tag. Used for load balancing when there are multiple image registry nodes.
|
||||
# keepalived_version: stable
|
||||
# keepalived_version: 2.0.20
|
||||
# ========== image registry: harbor ==========
|
||||
# harbor image tag
|
||||
# harbor_version: v2.10.1
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ spec:
|
|||
etcd_version: v3.5.11
|
||||
# ========== image registry ==========
|
||||
# keepalived image tag. Used for load balancing when there are multiple image registry nodes.
|
||||
# keepalived_version: stable
|
||||
# keepalived_version: 2.0.20
|
||||
# ========== image registry: harbor ==========
|
||||
# harbor image tag
|
||||
# harbor_version: v2.10.1
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ spec:
|
|||
etcd_version: v3.5.11
|
||||
# ========== image registry ==========
|
||||
# keepalived image tag. Used for load balancing when there are multiple image registry nodes.
|
||||
# keepalived_version: stable
|
||||
# keepalived_version: 2.0.20
|
||||
# ========== image registry: harbor ==========
|
||||
# harbor image tag
|
||||
# harbor_version: v2.10.1
|
||||
|
|
|
|||
|
|
@ -21,10 +21,10 @@
|
|||
{{- range .groups.etcd | default list -}}
|
||||
{{- $internalIPv4 := index $.hostvars . "internal_ipv4" | default "" -}}
|
||||
{{- $internalIPv6 := index $.hostvars . "internal_ipv6" | default "" -}}
|
||||
{{- if ne $internalIPv4 "" -}}
|
||||
{{- if $internalIPv4 | empty | not -}}
|
||||
{{- $ips = append $ips $internalIPv4 -}}
|
||||
{{- end -}}
|
||||
{{- if ne $internalIPv6 "" -}}
|
||||
{{- if $internalIPv6 | empty | not -}}
|
||||
{{- $ips = append $ips $internalIPv6 -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
|
@ -46,13 +46,16 @@
|
|||
cn: image_registry
|
||||
sans: >-
|
||||
{{- $ips := list -}}
|
||||
{{- if .image_registry.ha_vip | empty | not -}}
|
||||
{{- $ips = append $ips .image_registry.ha_vip -}}
|
||||
{{- end -}}
|
||||
{{- range .groups.image_registry | default list -}}
|
||||
{{- $internalIPv4 := index $.hostvars . "internal_ipv4" | default "" -}}
|
||||
{{- $internalIPv6 := index $.hostvars . "internal_ipv6" | default "" -}}
|
||||
{{- if ne $internalIPv4 "" -}}
|
||||
{{- if $internalIPv4 | empty | not -}}
|
||||
{{- $ips = append $ips $internalIPv4 -}}
|
||||
{{- end -}}
|
||||
{{- if ne $internalIPv6 "" -}}
|
||||
{{- if $internalIPv6 | empty | not -}}
|
||||
{{- $ips = append $ips $internalIPv6 -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ image_registry:
|
|||
nfs_dir: /share/registry
|
||||
storage:
|
||||
filesystem:
|
||||
rootdir: /var/lib/registry
|
||||
rootdir: /opt/registry/data
|
||||
# nfs_mount: /repository/registry # if set. will mount rootdirectory to nfs server in nfs_mount.
|
||||
# azure:
|
||||
# accountname: accountname
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
#!/bin/bash
|
||||
|
||||
nc -zv -w 2 localhost 443 > /dev/null 2>&1
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
register: docker_install_version
|
||||
|
||||
- name: Install docker
|
||||
when: .docker_install_version.stderr | empty | not) (.docker_install_version.stdout | hasPrefix (printf "Docker version %s," .docker_version) | not)
|
||||
when: or (.docker_install_version.stderr | empty | not) (.docker_install_version.stdout | hasPrefix (printf "Docker version %s," .docker_version) | not)
|
||||
block:
|
||||
- name: Sync docker binary to remote
|
||||
copy:
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
- name: Sync harbor package to remote
|
||||
copy:
|
||||
src: >-
|
||||
{{ .binary_dir }}/image-registry/harbor/{{ .harbor_version }}/{{ .binary_type.stdout }}/harbor-offline-installer-{{ .harbor_version }}.tgz
|
||||
{{ .binary_dir }}/image-registry/harbor/{{ .harbor_version }}/{{ .binary_type }}/harbor-offline-installer-{{ .harbor_version }}.tgz
|
||||
dest: >-
|
||||
/opt/harbor/{{ .harbor_version }}/harbor-offline-installer-{{ .harbor_version }}.tgz
|
||||
|
||||
|
|
@ -30,15 +30,6 @@
|
|||
dest: >-
|
||||
/opt/harbor/{{ .harbor_version }}/harbor/harbor.yml
|
||||
|
||||
- name: Generate keepalived docker compose
|
||||
template:
|
||||
src: harbor_keepalived.docker-compose
|
||||
dest: >-
|
||||
/opt/harbor/{{ .harbor_version }}/harbor/docker-compose-keepalived.yml
|
||||
when:
|
||||
- .image_registry.ha_vip | empty | not
|
||||
- .image_registry_service.stderr | empty | not
|
||||
|
||||
- name: Install harbor
|
||||
command: |
|
||||
cd /opt/harbor/{{ .harbor_version }}/harbor && /bin/bash install.sh
|
||||
|
|
@ -50,3 +41,62 @@
|
|||
|
||||
- name: Start harbor service
|
||||
command: systemctl daemon-reload && systemctl start harbor.service && systemctl enable harbor.service
|
||||
|
||||
- name: HA harbor sync images
|
||||
when:
|
||||
- .image_registry.ha_vip | empty | not
|
||||
- .groups.image_registry | len | lt 1
|
||||
block:
|
||||
- name: add keepalived service to docker-compose
|
||||
command: |
|
||||
KEEPALIVED_SERVICE='# keepalived is generated by kubekey.
|
||||
keepalived:
|
||||
image: osixia/keepalived:{{ .keepalived_version }}
|
||||
container_name: keepalived
|
||||
command:
|
||||
- --copy-service
|
||||
network_mode: "host"
|
||||
restart: always
|
||||
dns_search: .
|
||||
cap_drop:
|
||||
- ALL
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
- NET_BROADCAST
|
||||
- NET_RAW
|
||||
- CHOWN
|
||||
- DAC_OVERRIDE
|
||||
depends_on:
|
||||
- proxy
|
||||
volumes:
|
||||
- type: bind
|
||||
source: /opt/keepalived/{{ .keepalived_version }}/keepalived.conf
|
||||
target: /container/service/keepalived/assets/keepalived.conf
|
||||
- type: bind
|
||||
source: /opt/keepalived/{{ .keepalived_version }}/healthcheck.sh
|
||||
target: /etc/keepalived/healthcheck.sh'
|
||||
TARGET_FILE="/opt/harbor/{{ .harbor_version }}/harbor/docker-compose.yml"
|
||||
TMP_FILE="/opt/harbor/{{ .harbor_version }}/harbor/docker-compose.yml.tmp"
|
||||
awk -v service="$KEEPALIVED_SERVICE" '
|
||||
/^services:/ {
|
||||
print
|
||||
print service
|
||||
next
|
||||
}
|
||||
{ print }
|
||||
' "$TARGET_FILE" > "$TMP_FILE" && mv "$TMP_FILE" "$TARGET_FILE"
|
||||
systemctl restart harbor.service
|
||||
- name: wait harbor service ready
|
||||
command: |
|
||||
if ! timeout 300 bash -c 'while ! nc -zv localhost 443; do sleep 2; done'; then
|
||||
echo "ERROR: Harbor did not start within 5 minutes!"
|
||||
exit 1
|
||||
fi
|
||||
- name: sync harbor-replications scripts to remote
|
||||
template:
|
||||
src: harbor-replications.sh
|
||||
dest: /opt/harbor/scripts/harbor-replications.sh
|
||||
mode: 0755
|
||||
- name: execute harbor-replications.sh
|
||||
command: bash /opt/harbor/scripts/harbor-replications.sh
|
||||
|
||||
|
|
@ -1,23 +1,65 @@
|
|||
---
|
||||
- name: Get interface from ha_vip
|
||||
block:
|
||||
- name: Get all interface with cidr
|
||||
command: |
|
||||
ip -o addr show | awk '
|
||||
BEGIN {
|
||||
printf "[\n";
|
||||
first = 1;
|
||||
}
|
||||
/inet / && !/ lo|docker|br-|veth/ {
|
||||
if (!first) {
|
||||
printf ",\n";
|
||||
}
|
||||
first = 0;
|
||||
printf " {\n";
|
||||
printf " \"interface\": \"%s\",\n", $2;
|
||||
printf " \"cidr\": \"%s\"\n", $4;
|
||||
printf " }";
|
||||
}
|
||||
END {
|
||||
printf "\n]\n";
|
||||
}
|
||||
'
|
||||
register: interface
|
||||
register_type: json
|
||||
- name: filter interface by ha_vip
|
||||
set_fact:
|
||||
ha_vip_interface: >-
|
||||
{{- $interface := "" }}
|
||||
{{- range .interface.stdout | default list -}}
|
||||
{{- if .cidr | ipInCIDR | has $.image_registry.ha_vip -}}
|
||||
{{- $interface = .interface -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{ $interface }}
|
||||
- name: Check if network is exist
|
||||
assert:
|
||||
that: .kube_vip_interface | empty
|
||||
fail_msg: "cannot find network interface to match ha_vip"
|
||||
|
||||
- name: Sync keepalived image to remote
|
||||
copy:
|
||||
src: >-
|
||||
{{ .binary_dir }}/image-registry/keepalived/{{ .keepalived_version }}/{{ .binary_type.stdout }}/keepalived-{{ .keepalived_version }}-linux-{{ .binary_type.stdout }}.tgz
|
||||
{{ .binary_dir }}/image-registry/keepalived/{{ .keepalived_version }}/{{ .binary_type }}/keepalived-{{ .keepalived_version }}-linux-{{ .binary_type }}.tgz
|
||||
dest: >-
|
||||
/opt/keepalived/{{ .keepalived_version }}/keepalived-{{ .keepalived_version }}-linux-{{ .binary_type.stdout }}.tgz
|
||||
/opt/keepalived/{{ .keepalived_version }}/keepalived-{{ .keepalived_version }}-linux-{{ .binary_type }}.tgz
|
||||
|
||||
- name: Load keeplived image
|
||||
command: |
|
||||
docker load -i /opt/keepalived/{{ .keepalived_version }}/keepalived-{{ .keepalived_version }}-linux-{{ .binary_type.stdout }}.tgz
|
||||
docker load -i /opt/keepalived/{{ .keepalived_version }}/keepalived-{{ .keepalived_version }}-linux-{{ .binary_type }}.tgz
|
||||
|
||||
- name: Sync keeplived config to remote
|
||||
template:
|
||||
src: keeplived.config
|
||||
src: keepalived.conf
|
||||
dest: >-
|
||||
/opt/keeplived/{{ .keepalived_version }}/keepalived.conf
|
||||
/opt/keepalived/{{ .keepalived_version }}/keepalived.conf
|
||||
mode: 0664
|
||||
|
||||
- name: Sync healthcheck shell to remote
|
||||
template:
|
||||
src: keepalived.healthcheck
|
||||
copy:
|
||||
src: keepalived/healthcheck.sh
|
||||
dest: >-
|
||||
/opt/keeplived/{{ .keepalived_version }}/healthcheck.sh
|
||||
/opt/keepalived/{{ .keepalived_version }}/healthcheck.sh
|
||||
mode: 0755
|
||||
|
|
|
|||
|
|
@ -23,9 +23,8 @@
|
|||
mount -t nfs {{ $internalIPv6 }}:{{ .image_registry.registry.storage.filesystem.nfs_mount }} {{ .image_registry.registry.storage.filesystem.rootdir }}
|
||||
{{- end }}
|
||||
when:
|
||||
- and .image_registry.registry.storage.filesystem.nfs_mount (ne .image_registry.registry.storage.filesystem.nfs_mount "")
|
||||
- .image_registry.registry.storage.filesystem.nfs_mount | empty | not
|
||||
- .groups.nfs | default list | len | eq 1
|
||||
- .image_registry_service.stderr | empty | not
|
||||
|
||||
- name: Load registry image
|
||||
command: |
|
||||
|
|
@ -58,9 +57,16 @@
|
|||
/opt/registry/{{ .registry_version }}/config.yml
|
||||
|
||||
- name: Register registry service
|
||||
copy:
|
||||
template:
|
||||
src: registry.service
|
||||
dest: /etc/systemd/system/registry.service
|
||||
|
||||
- name: Start registry service
|
||||
command: systemctl daemon-reload && systemctl start registry.service && systemctl enable registry.service
|
||||
|
||||
- name: wait registry service ready
|
||||
command: |
|
||||
if ! timeout 300 bash -c 'while ! nc -zv localhost 443; do sleep 2; done'; then
|
||||
echo "ERROR: Harbor did not start within 5 minutes!"
|
||||
exit 1
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
done
|
||||
when: .image_registry.type | eq "harbor"
|
||||
|
||||
- name: Sync images package to harbor
|
||||
- name: Sync images package to image_registry
|
||||
tags: ["only_image"]
|
||||
image:
|
||||
push:
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@
|
|||
- include_tasks: install_docker_compose.yaml
|
||||
|
||||
- include_tasks: install_keepalived.yaml
|
||||
when: .image_registry.ha_vip | empty | not
|
||||
when:
|
||||
- .image_registry.ha_vip | empty | not
|
||||
- .groups.image_registry | len | lt 1
|
||||
|
||||
- name: Install harbor
|
||||
when: .image_registry.type | eq "harbor"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
#!/bin/bash
|
||||
|
||||
function createRegistries() {
|
||||
{{- range .groups.image_registry | default list }}
|
||||
{{- if ne . $.inventory_hostname }}
|
||||
curl -k -u '{{ printf "%s:%s" $.image_registry.auth.username $.image_registry.auth.password }}' -X POST -H "Content-Type: application/json" "https://{{ $.inventory_hostname }}/api/v2.0/registries" -d "{\"name\": \"{{ . }}\", \"type\": \"harbor\", \"url\":\"https://{{ . }}:7443\", \"credential\": {\"access_key\": \"{{ $.image_registry.auth.username }}\", \"access_secret\": \"{{ $.image_registry.auth.password }}\"}, \"insecure\": true}"
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
function createReplication() {
|
||||
{{- range $index, $host := .groups.image_registry | default list }}
|
||||
{{- if ne $host $.inventory_hostname }}
|
||||
curl -k -u '{{ printf "%s:%s" $.image_registry.auth.username $.image_registry.auth.password }}' -X POST -H "Content-Type: application/json" "https://{{ $.inventory_hostname }}/api/v2.0/replication/policies" -d "{\"name\": \"{{ printf "%s_%s" $.inventory_hostname $host }}\", \"enabled\": true, \"deletion\":true, \"override\":true, \"replicate_deletion\":true, \"dest_registry\":{ \"id\": {{ $index }}, \"name\": \"{{ $host }}\"}, \"trigger\": {\"type\": \"event_based\"}, \"dest_namespace_replace_count\":1 }"
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
createRegistries
|
||||
createReplication
|
||||
|
|
@ -5,7 +5,7 @@ Requires=docker.service
|
|||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/local/bin/docker-compose -p harbor -f /opt/harbor/{{ .harbor_version }}/harbor/docker-compose.yml up{{ if and .image_registry.ha_vip (ne .image_registry.ha_vip "") }} && /usr/local/bin/docker-compose -p harbor -f /opt/harbor/{{ .harbor_version }}/harbor/docker-compose-keepalived.yml up{{ end }}
|
||||
ExecStart=/usr/local/bin/docker-compose -p harbor -f /opt/harbor/{{ .harbor_version }}/harbor/docker-compose.yml up
|
||||
ExecStop=/usr/local/bin/docker-compose -p harbor down
|
||||
Restart=on-failure
|
||||
[Install]
|
||||
|
|
|
|||
|
|
@ -1,26 +0,0 @@
|
|||
---
|
||||
version: '2.3'
|
||||
services:
|
||||
keepalived:
|
||||
image: osixia/keepalived: {{ .keepalived_version }}
|
||||
container_name: keepalived
|
||||
restart: always
|
||||
dns_search: .
|
||||
cap_drop:
|
||||
- ALL
|
||||
cap_add:
|
||||
- CHOWN
|
||||
- DAC_OVERRIDE
|
||||
- SETGID
|
||||
- SETUID
|
||||
depends_on:
|
||||
- proxy
|
||||
volumes:
|
||||
- type: bind
|
||||
source: /opt/keeplived/{{ .keepalived_version }}/keepalived.conf
|
||||
target: /container/service/keepalived/assets/keepalived.conf
|
||||
- type: bind
|
||||
source: /opt/keeplived/{{ .keepalived_version }}/healthcheck.sh
|
||||
target: /etc/keepalived/healthcheck.sh
|
||||
networks:
|
||||
- harbor
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
vrrp_script healthcheck {
|
||||
script "/etc/keepalived/healthcheck.sh"
|
||||
interval 10
|
||||
fall 2
|
||||
rise 2
|
||||
timeout 5
|
||||
init_fail
|
||||
}
|
||||
global_defs {
|
||||
script_user root
|
||||
router_id harbor-ha
|
||||
enable_script_security
|
||||
}
|
||||
vrrp_instance VI_1 {
|
||||
state {{ if .groups.image_registry | first | eq .inventory_hostname }}MASTER{{ else }}BACKUP{{ end }}
|
||||
interface {{ .ha_vip_interface }}
|
||||
virtual_router_id 31
|
||||
priority 50
|
||||
advert_int 1
|
||||
authentication {
|
||||
auth_type PASS
|
||||
auth_pass k8s-test
|
||||
}
|
||||
virtual_ipaddress {
|
||||
{{ .image_registry.ha_vip }}
|
||||
}
|
||||
track_script {
|
||||
healthcheck
|
||||
}
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
vrrp_script healthcheck {
|
||||
script "/etc/keepalived/healthcheck.sh"
|
||||
interval 10
|
||||
fall 2
|
||||
rise 2
|
||||
timeout 5
|
||||
init_fail
|
||||
}
|
||||
global_defs {
|
||||
script_user root
|
||||
router_id harbor-ha
|
||||
enable_script_security
|
||||
lvs_sync_daemon ens3 VI_1
|
||||
}
|
||||
vrrp_instance VI_1 {
|
||||
state BACKUP
|
||||
interface ens3
|
||||
virtual_router_id 31
|
||||
priority 50
|
||||
advert_int 1
|
||||
authentication {
|
||||
auth_type PASS
|
||||
auth_pass k8s-test
|
||||
}
|
||||
virtual_ipaddress {
|
||||
{{ .image_registry.ha_vip }}
|
||||
}
|
||||
track_script {
|
||||
healthcheck
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
{{- if .image_registry.type | eq "registry" }}
|
||||
# registry service
|
||||
service=registry:5000
|
||||
{{- else }}
|
||||
# harbor service
|
||||
service=harbor:80
|
||||
{{- end }}
|
||||
|
||||
nc -zv -w 2 $service > /dev/null 2>&1
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -22,9 +22,9 @@ log:
|
|||
# to:
|
||||
# - errors@example.com
|
||||
storage:
|
||||
{{- if .image_registry.registry.storage.filesystem.rootdirectory | empty | not }}
|
||||
{{- if .image_registry.registry.storage.filesystem.rootdir | empty | not }}
|
||||
filesystem:
|
||||
rootdirectory: {{ .image_registry.registry.storage.filesystem.rootdirectory }}
|
||||
rootdirectory: {{ .image_registry.registry.storage.filesystem.rootdir }}
|
||||
maxthreads: 100
|
||||
{{- end }}
|
||||
{{- if .image_registry.registry.storage.azure }}
|
||||
|
|
@ -71,13 +71,13 @@ storage:
|
|||
usedualstack: false
|
||||
loglevel: debug
|
||||
{{- end }}
|
||||
inmemory: # This driver takes no parameters
|
||||
# inmemory: # This driver takes no parameters
|
||||
delete:
|
||||
enabled: false
|
||||
redirect:
|
||||
disable: false
|
||||
cache:
|
||||
blobdescriptor: redis
|
||||
blobdescriptor: inmemory
|
||||
blobdescriptorsize: 10000
|
||||
maintenance:
|
||||
uploadpurging:
|
||||
|
|
@ -124,7 +124,7 @@ storage:
|
|||
# options:
|
||||
# baseurl: https://example.com/
|
||||
http:
|
||||
addr: localhost:5000
|
||||
addr: 0.0.0.0:5000
|
||||
# prefix: /my/nested/registry/
|
||||
# host: https://myregistryaddress.org:5000
|
||||
secret: asecretforlocaldevelopment
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ services:
|
|||
- type: bind
|
||||
source: /opt/registry/{{ .registry_version }}/config.yml
|
||||
target: /etc/docker/registry/config.yml
|
||||
port:
|
||||
ports:
|
||||
- 443:5000
|
||||
networks:
|
||||
- registry
|
||||
|
|
@ -28,26 +28,28 @@ services:
|
|||
keepalived:
|
||||
image: osixia/keepalived:{{ .keepalived_version }}
|
||||
container_name: keepalived
|
||||
command:
|
||||
- --copy-service
|
||||
network_mode: "host"
|
||||
restart: always
|
||||
dns_search: .
|
||||
cap_drop:
|
||||
- ALL
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
- NET_BROADCAST
|
||||
- NET_RAW
|
||||
- CHOWN
|
||||
- DAC_OVERRIDE
|
||||
- SETGID
|
||||
- SETUID
|
||||
depends_on:
|
||||
- registry
|
||||
volumes:
|
||||
- type: bind
|
||||
source: /opt/keeplived/{{ .keepalived_version }}/keepalived.conf
|
||||
source: /opt/keepalived/{{ .keepalived_version }}/keepalived.conf
|
||||
target: /container/service/keepalived/assets/keepalived.conf
|
||||
- type: bind
|
||||
source: /opt/keeplived/{{ .keepalived_version }}/healthcheck.sh
|
||||
source: /opt/keepalived/{{ .keepalived_version }}/healthcheck.sh
|
||||
target: /etc/keepalived/healthcheck.sh
|
||||
networks:
|
||||
- registry
|
||||
{{- end }}
|
||||
networks:
|
||||
registry:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
[Unit]
|
||||
Description=harbor
|
||||
Description=registry
|
||||
After=docker.service systemd-networkd.service systemd-resolved.service
|
||||
Requires=docker.service
|
||||
|
||||
|
|
|
|||
|
|
@ -1,21 +1,42 @@
|
|||
---
|
||||
- name: Get network interface for kube_vip
|
||||
- name: Get interface from kube_vip
|
||||
block:
|
||||
- name: Get all interface with cidr
|
||||
command: |
|
||||
{{- if .kubernetes.control_plane_endpoint.kube_vip.address | ipFamily | eq "IPv4" }}
|
||||
ip route | grep '{{ .internal_ipv4 }}' | grep 'proto kernel scope link src' | awk '{print $3}'
|
||||
{{- else if .kubernetes.control_plane_endpoint.host | ipFamily | eq "IPv6" }}
|
||||
ip route | grep '{{ .internal_ipv6 }}' | grep 'proto kernel scope link src' | awk '{print $3}'
|
||||
{{- else }}
|
||||
echo "kubernetes.control_plane_endpoint.kube_vip.address" should be ipv4 or ipv6
|
||||
exit 1
|
||||
{{- end }}
|
||||
ip -o addr show | awk '
|
||||
BEGIN {
|
||||
printf "[\n";
|
||||
first = 1;
|
||||
}
|
||||
/inet / && !/ lo|docker|br-|veth/ {
|
||||
if (!first) {
|
||||
printf ",\n";
|
||||
}
|
||||
first = 0;
|
||||
printf " {\n";
|
||||
printf " \"interface\": \"%s\",\n", $2;
|
||||
printf " \"cidr\": \"%s\"\n", $4;
|
||||
printf " }";
|
||||
}
|
||||
END {
|
||||
printf "\n]\n";
|
||||
}
|
||||
'
|
||||
register: interface
|
||||
|
||||
- name: Check if network is exist
|
||||
register_type: json
|
||||
- name: filter interface by ha_vip
|
||||
set_fact:
|
||||
kube_vip_interface: >-
|
||||
{{- $interface := "" }}
|
||||
{{- range .interface.stdout | default list -}}
|
||||
{{- if .cidr | ipInCIDR | has $.kubernetes.control_plane_endpoint.kube_vip.address -}}
|
||||
{{- $interface = .interface -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{ $interface }}
|
||||
- name: Check if network is exist
|
||||
assert:
|
||||
that:
|
||||
- .interface.stderr | empty
|
||||
- .interface.stdout | empty | not
|
||||
that: .kube_vip_interface | empty
|
||||
fail_msg: "cannot find network interface to match kube_vip"
|
||||
|
||||
- name: Generate kube_vip manifest
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ spec:
|
|||
- name: port
|
||||
value: "6443"
|
||||
- name: vip_interface
|
||||
value: {{ .interface.stdout }}
|
||||
value: {{ .kube_vip_interface }}
|
||||
- name: vip_cidr
|
||||
value: "32"
|
||||
- name: cp_enable
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ spec:
|
|||
- name: port
|
||||
value: "6443"
|
||||
- name: vip_interface
|
||||
value: {{ .interface.stdout }}
|
||||
value: {{ .kube_vip_interface }}
|
||||
- name: vip_cidr
|
||||
value: "32"
|
||||
- name: cp_enable
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
# image_registry is installed by docker_compose
|
||||
- name: docker_version and dockercompose_version should not be empty
|
||||
when: .groups.image_registry | empty | not
|
||||
assert:
|
||||
that:
|
||||
- .docker_version | empty | not
|
||||
- .dockercompose_version | empty | not
|
||||
msg: >-
|
||||
"docker_version" and "dockercompose_version" should not be empty
|
||||
|
||||
- name: keepalived_version should not be empty when image_registry is high availability
|
||||
when:
|
||||
- .image_registry.ha_vip | empty | not
|
||||
- .groups.image_registry | len | lt 1
|
||||
assert:
|
||||
that: .keepalived_version | empty | not
|
||||
msg: >-
|
||||
"keepalived_version" should not be empty when image_registry is high availability
|
||||
|
|
@ -1,3 +1,8 @@
|
|||
- name: Delete arp by kube-vip
|
||||
command: |
|
||||
ip neigh show | grep {{ .image_registry.ha_vip }} | awk '{print $1 " dev " $3}' | xargs -r -L1 ip neigh delete
|
||||
ip -o addr show | grep {{ .image_registry.ha_vip }} | awk '{system("ip addr del "$4" dev "$2)}'
|
||||
|
||||
- name: Delete residue keepalived files
|
||||
command: |
|
||||
rm -rf /opt/keepalived/
|
||||
|
|
@ -0,0 +1,784 @@
|
|||
{
|
||||
"type": "excalidraw",
|
||||
"version": 2,
|
||||
"source": "https://excalidraw.com",
|
||||
"elements": [
|
||||
{
|
||||
"id": "o93_Uv5XcZbMQM0H30Zkq",
|
||||
"type": "rectangle",
|
||||
"x": 868,
|
||||
"y": 241,
|
||||
"width": 244,
|
||||
"height": 59.99999999999999,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#b2f2bb",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b7F",
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 865016729,
|
||||
"version": 290,
|
||||
"versionNonce": 326982455,
|
||||
"isDeleted": false,
|
||||
"boundElements": [
|
||||
{
|
||||
"type": "text",
|
||||
"id": "Q-e9pr0XedDsE8hLhtxpo"
|
||||
},
|
||||
{
|
||||
"id": "_oQQMRTunRyo9Zq43ZnJU",
|
||||
"type": "arrow"
|
||||
},
|
||||
{
|
||||
"id": "3wbQCkbDLOFDINm5zzTS-",
|
||||
"type": "arrow"
|
||||
},
|
||||
{
|
||||
"id": "LWBWVZxRHzET8YEmPb-f3",
|
||||
"type": "arrow"
|
||||
},
|
||||
{
|
||||
"id": "DQu2mOOAST7Qj33GexWWU",
|
||||
"type": "arrow"
|
||||
}
|
||||
],
|
||||
"updated": 1750302611172,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "Q-e9pr0XedDsE8hLhtxpo",
|
||||
"type": "text",
|
||||
"x": 926.0099983215332,
|
||||
"y": 258.5,
|
||||
"width": 127.9800033569336,
|
||||
"height": 25,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b7G",
|
||||
"roundness": null,
|
||||
"seed": 1864202359,
|
||||
"version": 274,
|
||||
"versionNonce": 2119579319,
|
||||
"isDeleted": false,
|
||||
"boundElements": null,
|
||||
"updated": 1750302514626,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"text": "harbor service",
|
||||
"fontSize": 20,
|
||||
"fontFamily": 6,
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": "o93_Uv5XcZbMQM0H30Zkq",
|
||||
"originalText": "harbor service",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "KcVtlaVjZmNTnyoeRJBfq",
|
||||
"type": "rectangle",
|
||||
"x": 486,
|
||||
"y": 245.5,
|
||||
"width": 244.00000000000003,
|
||||
"height": 60.000000000000014,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#b2f2bb",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b7H",
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1227906551,
|
||||
"version": 335,
|
||||
"versionNonce": 1110807543,
|
||||
"isDeleted": false,
|
||||
"boundElements": [
|
||||
{
|
||||
"type": "text",
|
||||
"id": "o1sccqOk7_faggHLFNheO"
|
||||
},
|
||||
{
|
||||
"id": "L8_xG3dqum2_YKMebNu2u",
|
||||
"type": "arrow"
|
||||
},
|
||||
{
|
||||
"id": "3wbQCkbDLOFDINm5zzTS-",
|
||||
"type": "arrow"
|
||||
},
|
||||
{
|
||||
"id": "LWBWVZxRHzET8YEmPb-f3",
|
||||
"type": "arrow"
|
||||
},
|
||||
{
|
||||
"id": "cO9D1owMBo5ciGKj9M8W7",
|
||||
"type": "arrow"
|
||||
}
|
||||
],
|
||||
"updated": 1750302607030,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "o1sccqOk7_faggHLFNheO",
|
||||
"type": "text",
|
||||
"x": 544.0099983215332,
|
||||
"y": 263,
|
||||
"width": 127.9800033569336,
|
||||
"height": 25,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b7I",
|
||||
"roundness": null,
|
||||
"seed": 1568638743,
|
||||
"version": 318,
|
||||
"versionNonce": 1300714231,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1750302560040,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"text": "harbor service",
|
||||
"fontSize": 20,
|
||||
"fontFamily": 6,
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": "KcVtlaVjZmNTnyoeRJBfq",
|
||||
"originalText": "harbor service",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "53tMOC8ghJAglooQgD-kW",
|
||||
"type": "rectangle",
|
||||
"x": 484,
|
||||
"y": 126,
|
||||
"width": 624,
|
||||
"height": 78,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#a5d8ff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b7J",
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 981932439,
|
||||
"version": 81,
|
||||
"versionNonce": 428276025,
|
||||
"isDeleted": false,
|
||||
"boundElements": [
|
||||
{
|
||||
"type": "text",
|
||||
"id": "neXgNEUOhJo1yjimmCiTH"
|
||||
},
|
||||
{
|
||||
"id": "L8_xG3dqum2_YKMebNu2u",
|
||||
"type": "arrow"
|
||||
},
|
||||
{
|
||||
"id": "_oQQMRTunRyo9Zq43ZnJU",
|
||||
"type": "arrow"
|
||||
}
|
||||
],
|
||||
"updated": 1750302564064,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "neXgNEUOhJo1yjimmCiTH",
|
||||
"type": "text",
|
||||
"x": 731.4399948120117,
|
||||
"y": 152.5,
|
||||
"width": 129.12001037597656,
|
||||
"height": 25,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b7K",
|
||||
"roundness": null,
|
||||
"seed": 1816398713,
|
||||
"version": 50,
|
||||
"versionNonce": 212167193,
|
||||
"isDeleted": false,
|
||||
"boundElements": null,
|
||||
"updated": 1750302564064,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"text": "Load Blanacer",
|
||||
"fontSize": 20,
|
||||
"fontFamily": 6,
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": "53tMOC8ghJAglooQgD-kW",
|
||||
"originalText": "Load Blanacer",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "edP1PJ_ABStEloX-Syel7",
|
||||
"type": "rectangle",
|
||||
"x": 488,
|
||||
"y": 337,
|
||||
"width": 244.00000000000003,
|
||||
"height": 60.000000000000014,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#b2f2bb",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b7N",
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 271586231,
|
||||
"version": 393,
|
||||
"versionNonce": 1107051063,
|
||||
"isDeleted": false,
|
||||
"boundElements": [
|
||||
{
|
||||
"type": "text",
|
||||
"id": "WaP95sXUDIWaHJ8dD3VlR"
|
||||
},
|
||||
{
|
||||
"id": "cO9D1owMBo5ciGKj9M8W7",
|
||||
"type": "arrow"
|
||||
}
|
||||
],
|
||||
"updated": 1750302607030,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "WaP95sXUDIWaHJ8dD3VlR",
|
||||
"type": "text",
|
||||
"x": 541.75,
|
||||
"y": 354.5,
|
||||
"width": 136.5,
|
||||
"height": 25,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b7O",
|
||||
"roundness": null,
|
||||
"seed": 511870167,
|
||||
"version": 388,
|
||||
"versionNonce": 1016794583,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1750302602385,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"text": "storage service",
|
||||
"fontSize": 20,
|
||||
"fontFamily": 6,
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": "edP1PJ_ABStEloX-Syel7",
|
||||
"originalText": "storage service",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "QnD-8-ujPJygThWv4oRRT",
|
||||
"type": "rectangle",
|
||||
"x": 872,
|
||||
"y": 336,
|
||||
"width": 244.00000000000003,
|
||||
"height": 60.000000000000014,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#b2f2bb",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b7P",
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 303174871,
|
||||
"version": 384,
|
||||
"versionNonce": 384514423,
|
||||
"isDeleted": false,
|
||||
"boundElements": [
|
||||
{
|
||||
"type": "text",
|
||||
"id": "zvSBobCjWHUzU-fOWcJLi"
|
||||
},
|
||||
{
|
||||
"id": "DQu2mOOAST7Qj33GexWWU",
|
||||
"type": "arrow"
|
||||
}
|
||||
],
|
||||
"updated": 1750302611172,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "zvSBobCjWHUzU-fOWcJLi",
|
||||
"type": "text",
|
||||
"x": 925.75,
|
||||
"y": 353.5,
|
||||
"width": 136.5,
|
||||
"height": 25,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b7Q",
|
||||
"roundness": null,
|
||||
"seed": 1388798455,
|
||||
"version": 379,
|
||||
"versionNonce": 1293090647,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1750302598218,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"text": "storage service",
|
||||
"fontSize": 20,
|
||||
"fontFamily": 6,
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": "QnD-8-ujPJygThWv4oRRT",
|
||||
"originalText": "storage service",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "L8_xG3dqum2_YKMebNu2u",
|
||||
"type": "arrow",
|
||||
"x": 789.8272747713355,
|
||||
"y": 204.9990705847769,
|
||||
"width": 130.79362370312788,
|
||||
"height": 39.02567346207175,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#b2f2bb",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b7R",
|
||||
"roundness": {
|
||||
"type": 2
|
||||
},
|
||||
"seed": 383988983,
|
||||
"version": 166,
|
||||
"versionNonce": 2021834489,
|
||||
"isDeleted": false,
|
||||
"boundElements": null,
|
||||
"updated": 1750302564064,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
-130.79362370312788,
|
||||
39.02567346207175
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "53tMOC8ghJAglooQgD-kW",
|
||||
"focus": -0.2888910803214833,
|
||||
"gap": 7
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "KcVtlaVjZmNTnyoeRJBfq",
|
||||
"focus": -0.2441231343283578,
|
||||
"gap": 5.5
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": false
|
||||
},
|
||||
{
|
||||
"id": "_oQQMRTunRyo9Zq43ZnJU",
|
||||
"type": "arrow",
|
||||
"x": 862.5126006477127,
|
||||
"y": 204.99907058477686,
|
||||
"width": 142.14928077039178,
|
||||
"height": 33.100855462394435,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#b2f2bb",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b7S",
|
||||
"roundness": {
|
||||
"type": 2
|
||||
},
|
||||
"seed": 72016441,
|
||||
"version": 108,
|
||||
"versionNonce": 732067801,
|
||||
"isDeleted": false,
|
||||
"boundElements": null,
|
||||
"updated": 1750302564064,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
142.14928077039178,
|
||||
33.100855462394435
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "53tMOC8ghJAglooQgD-kW",
|
||||
"focus": 0.2194976788477558,
|
||||
"gap": 7
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "o93_Uv5XcZbMQM0H30Zkq",
|
||||
"focus": 0.6222604211431018,
|
||||
"gap": 10
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": false
|
||||
},
|
||||
{
|
||||
"id": "3wbQCkbDLOFDINm5zzTS-",
|
||||
"type": "arrow",
|
||||
"x": 739.5702440443347,
|
||||
"y": 258.96307786317976,
|
||||
"width": 118.85951191133074,
|
||||
"height": 0.014658463536704858,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#b2f2bb",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "dashed",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b7T",
|
||||
"roundness": {
|
||||
"type": 2
|
||||
},
|
||||
"seed": 1405197335,
|
||||
"version": 135,
|
||||
"versionNonce": 1501321783,
|
||||
"isDeleted": false,
|
||||
"boundElements": null,
|
||||
"updated": 1750302560193,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
118.85951191133074,
|
||||
0.014658463536704858
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "KcVtlaVjZmNTnyoeRJBfq",
|
||||
"focus": -0.5514950166112959,
|
||||
"gap": 10
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "o93_Uv5XcZbMQM0H30Zkq",
|
||||
"focus": 0.3999999999999996,
|
||||
"gap": 10
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": false
|
||||
},
|
||||
{
|
||||
"id": "LWBWVZxRHzET8YEmPb-f3",
|
||||
"type": "arrow",
|
||||
"x": 858.4297559556653,
|
||||
"y": 279.2973724995128,
|
||||
"width": 120.65385031474193,
|
||||
"height": 1.916023220647503,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#b2f2bb",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "dashed",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b7U",
|
||||
"roundness": {
|
||||
"type": 2
|
||||
},
|
||||
"seed": 67343543,
|
||||
"version": 140,
|
||||
"versionNonce": 1144521719,
|
||||
"isDeleted": false,
|
||||
"boundElements": null,
|
||||
"updated": 1750302574470,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
-120.65385031474193,
|
||||
1.916023220647503
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "o93_Uv5XcZbMQM0H30Zkq",
|
||||
"focus": -0.156993339676499,
|
||||
"gap": 10
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "KcVtlaVjZmNTnyoeRJBfq",
|
||||
"focus": 0.24342244771700097,
|
||||
"gap": 7.7759056409233835
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": false
|
||||
},
|
||||
{
|
||||
"id": "dBCR-0VHhAZrQsuybKfxf",
|
||||
"type": "text",
|
||||
"x": 746,
|
||||
"y": 290,
|
||||
"width": 110.52000427246094,
|
||||
"height": 25,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#b2f2bb",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "dashed",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b7V",
|
||||
"roundness": null,
|
||||
"seed": 1033720663,
|
||||
"version": 68,
|
||||
"versionNonce": 931739607,
|
||||
"isDeleted": false,
|
||||
"boundElements": null,
|
||||
"updated": 1750302594968,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"text": "sync images",
|
||||
"fontSize": 20,
|
||||
"fontFamily": 6,
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top",
|
||||
"containerId": null,
|
||||
"originalText": "sync images",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "cO9D1owMBo5ciGKj9M8W7",
|
||||
"type": "arrow",
|
||||
"x": 610,
|
||||
"y": 313,
|
||||
"width": 0,
|
||||
"height": 15,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#b2f2bb",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "dashed",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b7W",
|
||||
"roundness": {
|
||||
"type": 2
|
||||
},
|
||||
"seed": 1108486455,
|
||||
"version": 11,
|
||||
"versionNonce": 745405719,
|
||||
"isDeleted": false,
|
||||
"boundElements": null,
|
||||
"updated": 1750302607030,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
15
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "KcVtlaVjZmNTnyoeRJBfq",
|
||||
"focus": -0.016393442622950786,
|
||||
"gap": 7.5
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "edP1PJ_ABStEloX-Syel7",
|
||||
"focus": 0,
|
||||
"gap": 9
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": false
|
||||
},
|
||||
{
|
||||
"id": "DQu2mOOAST7Qj33GexWWU",
|
||||
"type": "arrow",
|
||||
"x": 1004,
|
||||
"y": 311,
|
||||
"width": 0,
|
||||
"height": 17,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#b2f2bb",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "dashed",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b7X",
|
||||
"roundness": {
|
||||
"type": 2
|
||||
},
|
||||
"seed": 572285047,
|
||||
"version": 11,
|
||||
"versionNonce": 1740299351,
|
||||
"isDeleted": false,
|
||||
"boundElements": null,
|
||||
"updated": 1750302611172,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
17
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "o93_Uv5XcZbMQM0H30Zkq",
|
||||
"focus": -0.11475409836065573,
|
||||
"gap": 10
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "QnD-8-ujPJygThWv4oRRT",
|
||||
"focus": 0.08196721311475404,
|
||||
"gap": 8
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": false
|
||||
}
|
||||
],
|
||||
"appState": {
|
||||
"gridSize": 20,
|
||||
"gridStep": 5,
|
||||
"gridModeEnabled": false,
|
||||
"viewBackgroundColor": "#ffffff",
|
||||
"lockedMultiSelections": {}
|
||||
},
|
||||
"files": {}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 84 KiB |
|
|
@ -0,0 +1,551 @@
|
|||
{
|
||||
"type": "excalidraw",
|
||||
"version": 2,
|
||||
"source": "https://excalidraw.com",
|
||||
"elements": [
|
||||
{
|
||||
"id": "o93_Uv5XcZbMQM0H30Zkq",
|
||||
"type": "rectangle",
|
||||
"x": 868,
|
||||
"y": 241,
|
||||
"width": 244,
|
||||
"height": 59.99999999999999,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#b2f2bb",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b7F",
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 865016729,
|
||||
"version": 292,
|
||||
"versionNonce": 497225262,
|
||||
"isDeleted": false,
|
||||
"boundElements": [
|
||||
{
|
||||
"type": "text",
|
||||
"id": "Q-e9pr0XedDsE8hLhtxpo"
|
||||
},
|
||||
{
|
||||
"id": "_oQQMRTunRyo9Zq43ZnJU",
|
||||
"type": "arrow"
|
||||
},
|
||||
{
|
||||
"id": "DQu2mOOAST7Qj33GexWWU",
|
||||
"type": "arrow"
|
||||
}
|
||||
],
|
||||
"updated": 1750924036450,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "Q-e9pr0XedDsE8hLhtxpo",
|
||||
"type": "text",
|
||||
"x": 921.1600036621094,
|
||||
"y": 258.5,
|
||||
"width": 137.67999267578125,
|
||||
"height": 25,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b7G",
|
||||
"roundness": null,
|
||||
"seed": 1864202359,
|
||||
"version": 282,
|
||||
"versionNonce": 697610606,
|
||||
"isDeleted": false,
|
||||
"boundElements": null,
|
||||
"updated": 1750924050371,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"text": "registry service",
|
||||
"fontSize": 20,
|
||||
"fontFamily": 6,
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": "o93_Uv5XcZbMQM0H30Zkq",
|
||||
"originalText": "registry service",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "KcVtlaVjZmNTnyoeRJBfq",
|
||||
"type": "rectangle",
|
||||
"x": 486,
|
||||
"y": 245.5,
|
||||
"width": 244.00000000000003,
|
||||
"height": 60.000000000000014,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#b2f2bb",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b7H",
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1227906551,
|
||||
"version": 337,
|
||||
"versionNonce": 1529332210,
|
||||
"isDeleted": false,
|
||||
"boundElements": [
|
||||
{
|
||||
"type": "text",
|
||||
"id": "o1sccqOk7_faggHLFNheO"
|
||||
},
|
||||
{
|
||||
"id": "L8_xG3dqum2_YKMebNu2u",
|
||||
"type": "arrow"
|
||||
},
|
||||
{
|
||||
"id": "cO9D1owMBo5ciGKj9M8W7",
|
||||
"type": "arrow"
|
||||
}
|
||||
],
|
||||
"updated": 1750924036450,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "o1sccqOk7_faggHLFNheO",
|
||||
"type": "text",
|
||||
"x": 539.1600036621094,
|
||||
"y": 263,
|
||||
"width": 137.67999267578125,
|
||||
"height": 25,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b7I",
|
||||
"roundness": null,
|
||||
"seed": 1568638743,
|
||||
"version": 328,
|
||||
"versionNonce": 511754546,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1750924033996,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"text": "registry service",
|
||||
"fontSize": 20,
|
||||
"fontFamily": 6,
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": "KcVtlaVjZmNTnyoeRJBfq",
|
||||
"originalText": "registry service",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "53tMOC8ghJAglooQgD-kW",
|
||||
"type": "rectangle",
|
||||
"x": 484,
|
||||
"y": 126,
|
||||
"width": 624,
|
||||
"height": 78,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#a5d8ff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b7J",
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 981932439,
|
||||
"version": 81,
|
||||
"versionNonce": 428276025,
|
||||
"isDeleted": false,
|
||||
"boundElements": [
|
||||
{
|
||||
"type": "text",
|
||||
"id": "neXgNEUOhJo1yjimmCiTH"
|
||||
},
|
||||
{
|
||||
"id": "L8_xG3dqum2_YKMebNu2u",
|
||||
"type": "arrow"
|
||||
},
|
||||
{
|
||||
"id": "_oQQMRTunRyo9Zq43ZnJU",
|
||||
"type": "arrow"
|
||||
}
|
||||
],
|
||||
"updated": 1750302564064,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "neXgNEUOhJo1yjimmCiTH",
|
||||
"type": "text",
|
||||
"x": 731.4399948120117,
|
||||
"y": 152.5,
|
||||
"width": 129.12001037597656,
|
||||
"height": 25,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b7K",
|
||||
"roundness": null,
|
||||
"seed": 1816398713,
|
||||
"version": 50,
|
||||
"versionNonce": 212167193,
|
||||
"isDeleted": false,
|
||||
"boundElements": null,
|
||||
"updated": 1750302564064,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"text": "Load Blanacer",
|
||||
"fontSize": 20,
|
||||
"fontFamily": 6,
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": "53tMOC8ghJAglooQgD-kW",
|
||||
"originalText": "Load Blanacer",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "edP1PJ_ABStEloX-Syel7",
|
||||
"type": "rectangle",
|
||||
"x": 488,
|
||||
"y": 383,
|
||||
"width": 628,
|
||||
"height": 60.000000000000014,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#b2f2bb",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b7N",
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 271586231,
|
||||
"version": 458,
|
||||
"versionNonce": 1441604658,
|
||||
"isDeleted": false,
|
||||
"boundElements": [
|
||||
{
|
||||
"type": "text",
|
||||
"id": "WaP95sXUDIWaHJ8dD3VlR"
|
||||
},
|
||||
{
|
||||
"id": "cO9D1owMBo5ciGKj9M8W7",
|
||||
"type": "arrow"
|
||||
},
|
||||
{
|
||||
"id": "DQu2mOOAST7Qj33GexWWU",
|
||||
"type": "arrow"
|
||||
}
|
||||
],
|
||||
"updated": 1750924054994,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "WaP95sXUDIWaHJ8dD3VlR",
|
||||
"type": "text",
|
||||
"x": 733.75,
|
||||
"y": 400.5,
|
||||
"width": 136.5,
|
||||
"height": 25,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b7O",
|
||||
"roundness": null,
|
||||
"seed": 511870167,
|
||||
"version": 452,
|
||||
"versionNonce": 81645042,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1750924054994,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"text": "storage service",
|
||||
"fontSize": 20,
|
||||
"fontFamily": 6,
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": "edP1PJ_ABStEloX-Syel7",
|
||||
"originalText": "storage service",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "L8_xG3dqum2_YKMebNu2u",
|
||||
"type": "arrow",
|
||||
"x": 789.8336419760351,
|
||||
"y": 204.99907058477686,
|
||||
"width": 130.72171598152477,
|
||||
"height": 39.02567346207178,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#b2f2bb",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b7R",
|
||||
"roundness": {
|
||||
"type": 2
|
||||
},
|
||||
"seed": 383988983,
|
||||
"version": 167,
|
||||
"versionNonce": 798245042,
|
||||
"isDeleted": false,
|
||||
"boundElements": null,
|
||||
"updated": 1750924028531,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
-130.72171598152477,
|
||||
39.02567346207178
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "53tMOC8ghJAglooQgD-kW",
|
||||
"focus": -0.2888910803214833,
|
||||
"gap": 7
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "KcVtlaVjZmNTnyoeRJBfq",
|
||||
"focus": -0.2441231343283578,
|
||||
"gap": 5.5
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": false
|
||||
},
|
||||
{
|
||||
"id": "_oQQMRTunRyo9Zq43ZnJU",
|
||||
"type": "arrow",
|
||||
"x": 862.5126006477127,
|
||||
"y": 204.99907058477686,
|
||||
"width": 142.14928077039178,
|
||||
"height": 33.100855462394435,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#b2f2bb",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b7S",
|
||||
"roundness": {
|
||||
"type": 2
|
||||
},
|
||||
"seed": 72016441,
|
||||
"version": 108,
|
||||
"versionNonce": 732067801,
|
||||
"isDeleted": false,
|
||||
"boundElements": null,
|
||||
"updated": 1750302564064,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
142.14928077039178,
|
||||
33.100855462394435
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "53tMOC8ghJAglooQgD-kW",
|
||||
"focus": 0.2194976788477558,
|
||||
"gap": 7
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "o93_Uv5XcZbMQM0H30Zkq",
|
||||
"focus": 0.6222604211431018,
|
||||
"gap": 10
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": false
|
||||
},
|
||||
{
|
||||
"id": "cO9D1owMBo5ciGKj9M8W7",
|
||||
"type": "arrow",
|
||||
"x": 655.6624775795378,
|
||||
"y": 307.58611094053396,
|
||||
"width": 103.19328237376556,
|
||||
"height": 74.33503752082942,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#b2f2bb",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "dashed",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b7W",
|
||||
"roundness": {
|
||||
"type": 2
|
||||
},
|
||||
"seed": 1108486455,
|
||||
"version": 120,
|
||||
"versionNonce": 1804812210,
|
||||
"isDeleted": false,
|
||||
"boundElements": null,
|
||||
"updated": 1750924054995,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
103.19328237376556,
|
||||
74.33503752082942
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "KcVtlaVjZmNTnyoeRJBfq",
|
||||
"focus": -0.016393442622950786,
|
||||
"gap": 7.5
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "edP1PJ_ABStEloX-Syel7",
|
||||
"focus": 0,
|
||||
"gap": 9
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": false
|
||||
},
|
||||
{
|
||||
"id": "DQu2mOOAST7Qj33GexWWU",
|
||||
"type": "arrow",
|
||||
"x": 966.2341709724777,
|
||||
"y": 303.90007395282873,
|
||||
"width": 99.30046503552558,
|
||||
"height": 78.16233299063248,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#b2f2bb",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "dashed",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "b7X",
|
||||
"roundness": {
|
||||
"type": 2
|
||||
},
|
||||
"seed": 572285047,
|
||||
"version": 91,
|
||||
"versionNonce": 1177844082,
|
||||
"isDeleted": false,
|
||||
"boundElements": null,
|
||||
"updated": 1750924054995,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
-99.30046503552558,
|
||||
78.16233299063248
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "o93_Uv5XcZbMQM0H30Zkq",
|
||||
"focus": -0.11475409836065573,
|
||||
"gap": 10
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "edP1PJ_ABStEloX-Syel7",
|
||||
"focus": 0.07278735375547067,
|
||||
"gap": 8
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": false
|
||||
}
|
||||
],
|
||||
"appState": {
|
||||
"gridSize": 20,
|
||||
"gridStep": 5,
|
||||
"gridModeEnabled": false,
|
||||
"viewBackgroundColor": "#ffffff",
|
||||
"lockedMultiSelections": {}
|
||||
},
|
||||
"files": {}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 79 KiB |
|
|
@ -47,6 +47,8 @@ precheck 集群安装前,对集群节点进行检查是否满足集群安装
|
|||
- **containerd 版本检查**: 当使用 containerd 作为容器管理器时,验证 containerd 版本是否满足最低版本要求
|
||||
**nfs_precheck**: NFS 存储检查,包括:
|
||||
- **NFS 服务器数量检查**: 验证集群中只能有一个 NFS 服务器节点,确保 NFS 服务部署的唯一性
|
||||
**image_registry_precheck**: 镜像仓库检查,包括:
|
||||
- **镜像仓库必要软件检查**: 需检查 `docker_version` 和 `dockercompose_version` 均已配置且不为空。镜像仓库通过 docker_compose 进行安装,缺少必要软件会导致安装失败。
|
||||
|
||||
## init
|
||||
|
||||
|
|
@ -78,6 +80,6 @@ post_hook 阶段在集群安装完成后执行,负责集群的最终配置和
|
|||
2. 设置脚本文件权限为 0755
|
||||
3. 遍历每个远程节点上 `/etc/kubekey/scripts/` 目录下所有 `post_install_*.sh` 文件,并执行该脚本文件
|
||||
|
||||
> work_dir: 工作目录,默认当前命令执行目录。
|
||||
> inventory_hostname: Inventory.yaml 文件中定义的host对应的名称。
|
||||
> **work_dir**: 工作目录,默认当前命令执行目录。
|
||||
> **inventory_hostname**: Inventory.yaml 文件中定义的host对应的名称。
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,245 @@
|
|||
# image_registry
|
||||
|
||||
image_registry允许用户安装镜像仓库。支持harbor和registry两种镜像仓库
|
||||
|
||||
## requirement
|
||||
|
||||
- 一台或多台运行兼容 deb/rpm 的 Linux 操作系统的计算机;例如:Ubuntu 或 CentOS。
|
||||
- 每台机器 8 GB 以上的内存,内存不足时应用会受限制。
|
||||
- 用作控制平面节点的计算机上至少有 4 个 CPU。
|
||||
- 集群中所有计算机之间具有完全的网络连接。你可以使用公共网络或专用网络
|
||||
- 使用本地存储时。计算机需要100G高速存储的磁盘空间。
|
||||
|
||||
## 安装harbor
|
||||
|
||||
### 构建Inventory
|
||||
```yaml
|
||||
apiVersion: kubekey.kubesphere.io/v1
|
||||
kind: Inventory
|
||||
metadata:
|
||||
name: default
|
||||
spec:
|
||||
hosts: # your can set all nodes here. or set nodes on special groups.
|
||||
# node1:
|
||||
# connector:
|
||||
# type: ssh
|
||||
# host: node1
|
||||
# port: 22
|
||||
# user: root
|
||||
# password: 123456
|
||||
groups:
|
||||
# all kubernetes nodes.
|
||||
k8s_cluster:
|
||||
groups:
|
||||
- kube_control_plane
|
||||
- kube_worker
|
||||
# control_plane nodes
|
||||
kube_control_plane:
|
||||
hosts:
|
||||
- localhost
|
||||
# worker nodes
|
||||
kube_worker:
|
||||
hosts:
|
||||
- localhost
|
||||
# etcd nodes when etcd_deployment_type is external
|
||||
etcd:
|
||||
hosts:
|
||||
- localhost
|
||||
image_registry:
|
||||
hosts:
|
||||
- localhost
|
||||
# nfs nodes for registry storage. and kubernetes nfs storage
|
||||
# nfs:
|
||||
# hosts:
|
||||
# - localhost
|
||||
|
||||
```
|
||||
需设置 `image_registry` 组
|
||||
|
||||
### 安装
|
||||
harbor是默认安装的镜像仓库
|
||||
1. 安装前检查
|
||||
```shell
|
||||
kk precheck image_registry -i inventory.yaml --set harbor_version=v2.10.1,docker_version=24.0.7,dockercompose_version=v2.20.3
|
||||
```
|
||||
2. 安装
|
||||
- 单独安装
|
||||
`image_registry` 可以脱离集群单独进行安装。
|
||||
```shell
|
||||
kk init registry -i inventory.yaml --set harbor_version=v2.10.1,docker_version=24.0.7,dockercompose_version=v2.20.3
|
||||
```
|
||||
|
||||
- 在创建集群时,自动安装
|
||||
在创建集群时,会检测 `image_registry` 节点是否安装了harbor, 没有安装时会自动根据配置安装harbor。
|
||||
```shell
|
||||
kk create cluster -i inventory.yaml --set harbor_version=v2.10.1,docker_version=24.0.7, dockercompose_version=v2.20.3
|
||||
```
|
||||
|
||||
### harbor高可用
|
||||
|
||||
harbor高可用有两种实现方式。
|
||||
|
||||
1. 每个harbor共享同一个存储服务。
|
||||
官方做法,适用于在kubernetes集群中安装。需要独立部署PostgreSQL 和 Redis 服务
|
||||
参考:https://goharbor.io/docs/edge/install-config/harbor-ha-helm/
|
||||
|
||||
2. 每个harbor有单独的存储服务。
|
||||
kubekey的做法,适用于在服务器上安装。
|
||||

|
||||
- load balancer: 通过docker compose部署keepalived服务实现。
|
||||
- harbor service: 通过docker compose部署harbor实现。
|
||||
- sync images: 通过harbor的复制管理功能实现。
|
||||
|
||||
安装示例:
|
||||
```shell
|
||||
./kk init registry -i inventory.yaml --set image_registry.ha_vip=xx.xx.xx.xx --set harbor_version=v2.10.1,docker_version=24.0.7,dockercompose_version=v2.20.3 --set keepalived_version=2.0.20,artifact.artifact_url.keepalived.amd64=keepalived-2.0.20-linux-amd64.tgz
|
||||
```
|
||||
1. 在inventory中的image_registry 组中设置多个节点
|
||||
|
||||
2. 设置变量`image_registry.ha_vip` ha_vip 是负载均衡的入口
|
||||
|
||||
3. 设置变量 `keepalived_version` 和 `artifact.artifact_url.keepalived.amd64` keepalived 是用于负载均衡的镜像。目前kubekey并未提供下载地址,可通过手动打包的方式来实现。
|
||||
```shell
|
||||
# download keepalived images
|
||||
docker pull osixia/keepalived:{{ .keepalived_version }}
|
||||
# package image
|
||||
docker save -o keepalived-{{ .keepalived_version }}-linux-{{ .binary_type }}.tgz osixia/ keepalived:{{ .keepalived_version }}
|
||||
# move image to workdir
|
||||
mv keepalived-{{ .keepalived_version }}-linux-{{ .binary_type }}.tgz {{ .binary_dir }}/ image-registry/keepalived/{{ .keepalived_version }}/{{ .binary_type }}/
|
||||
```
|
||||
`binary_type`: 是机器的架构(目前支持amd64和arm64,可通过 `gather_fact` 自动获取)
|
||||
`binary_dir`: 软件包存放地址,通常为: `{{ .work_dir}}/kubekey`
|
||||
|
||||
4. 设置变量 `harbor_version`, `docker_version` 和 `dockercompose_version`。harbor通过docker-compose进行安装。
|
||||
|
||||
|
||||
## 安装registry
|
||||
|
||||
### 构建Inventory
|
||||
```yaml
|
||||
apiVersion: kubekey.kubesphere.io/v1
|
||||
kind: Inventory
|
||||
metadata:
|
||||
name: default
|
||||
spec:
|
||||
hosts: # your can set all nodes here. or set nodes on special groups.
|
||||
# node1:
|
||||
# connector:
|
||||
# type: ssh
|
||||
# host: node1
|
||||
# port: 22
|
||||
# user: root
|
||||
# password: 123456
|
||||
groups:
|
||||
# all kubernetes nodes.
|
||||
k8s_cluster:
|
||||
groups:
|
||||
- kube_control_plane
|
||||
- kube_worker
|
||||
# control_plane nodes
|
||||
kube_control_plane:
|
||||
hosts:
|
||||
- localhost
|
||||
# worker nodes
|
||||
kube_worker:
|
||||
hosts:
|
||||
- localhost
|
||||
# etcd nodes when etcd_deployment_type is external
|
||||
etcd:
|
||||
hosts:
|
||||
- localhost
|
||||
image_registry:
|
||||
hosts:
|
||||
- localhost
|
||||
# nfs nodes for registry storage. and kubernetes nfs storage
|
||||
# nfs:
|
||||
# hosts:
|
||||
# - localhost
|
||||
|
||||
```
|
||||
### 构建 registry 镜像包
|
||||
kubekey暂未提供registry的离线镜像包地址,需通过手动打包的方式来实现。
|
||||
```shell
|
||||
# download registry images
|
||||
docker pull registry:{{ .registry_version }}
|
||||
# package image
|
||||
docker save -o registry-{{ .registry_version }}-linux-{{ .binary_type }}.tgz registry:{{ .registry_version }}
|
||||
# move image to workdir
|
||||
mv registry-{{ .registry_version }}-linux-{{ .binary_type }}.tgz {{ .binary_dir }}/ image-registry/registry/{{ .registry_version }}/{{ .binary_type }}/
|
||||
```
|
||||
`binary_type`: 是机器的架构(目前支持amd64和arm64,可通过 `gather_fact` 自动获取)
|
||||
`binary_dir`: 软件包存放地址,通常为: `{{ .work_dir}}/kubekey`
|
||||
|
||||
### 安装
|
||||
安装registry需要设置`image_registry.type`值为`registry`
|
||||
1. 安装前检查
|
||||
```shell
|
||||
kk precheck image_registry -i inventory.yaml --set image_registry.type=registry --set registry_version=2.8.3,docker_version=24.0.7,dockercompose_version=v2.20.3
|
||||
```
|
||||
2. 安装
|
||||
- 单独安装
|
||||
`image_registry` 可以脱离集群单独进行安装。
|
||||
```shell
|
||||
kk init registry -i inventory.yaml --set image_registry.type=registry --set registry_version=2.8.3,docker_version=24.0.7,dockercompose_version=v2.20.3 --set artifact.artifact_url.registry.amd64=registry-2.8.3-linux.amd64.tgz
|
||||
```
|
||||
|
||||
- 在创建集群时,自动安装
|
||||
在创建集群时,会检测 `image_registry` 节点是否安装了harbor, 没有安装时会自动根据配置安装harbor。
|
||||
```shell
|
||||
kk create cluster -i inventory.yaml --set image_registry.type=registry --set registry_version=2.8.3,docker_version=24.0.7,dockercompose_version=v2.20.3 --set artifact.artifact_url.registry.amd64=registry-2.8.3-linux.amd64.tgz
|
||||
```
|
||||
|
||||
### registry高可用
|
||||
|
||||

|
||||
- load balancer: 通过docker compose部署keepalived服务实现。
|
||||
- registry service: 通过docker compose部署registry实现。
|
||||
- storage service: registry 高可用可通过共享存储的方式来实现。registry 支持多种存储后端,常见的有:
|
||||
- **filesystem**: 本地存储。默认情况下,registry 使用本地磁盘存储镜像数据。如果需要实现高可用,可以将本地存储目 录挂载到 NFS 等共享存储上。配置示例:
|
||||
```yaml
|
||||
image_registry:
|
||||
registry:
|
||||
storage:
|
||||
filesystem:
|
||||
rootdir: /opt/registry/data
|
||||
nfs_mount: /repository/registry # 可选,将 rootdir 挂载到 NFS 服务器
|
||||
```
|
||||
需要在 `nfs` 节点配置和挂载好共享目录,保证所有 registry 实例的数据一致性。
|
||||
|
||||
- **azure**: 使用 Azure Blob Storage 作为后端存储。适用于部署在 Azure 云环境下的场景。配置示例:
|
||||
```yaml
|
||||
image_registry:
|
||||
registry:
|
||||
storage:
|
||||
azure:
|
||||
accountname: <your-account-name>
|
||||
accountkey: <your-account-key>
|
||||
container: <your-container-name>
|
||||
```
|
||||
|
||||
- **gcs**: 使用 Google Cloud Storage 作为后端存储。适用于部署在 GCP 云环境下的场景。配置示例:
|
||||
```yaml
|
||||
image_registry:
|
||||
registry:
|
||||
storage:
|
||||
gcs:
|
||||
bucket: <your-bucket-name>
|
||||
keyfile: /path/to/keyfile.json
|
||||
```
|
||||
|
||||
- **s3**: 使用 Amazon S3 或兼容 S3 协议的对象存储作为后端存储。适用于 AWS 或支持 S3 协议的私有云。配置示例:
|
||||
```yaml
|
||||
image_registry:
|
||||
registry:
|
||||
storage:
|
||||
s3:
|
||||
accesskey: <your-access-key>
|
||||
secretkey: <your-secret-key>
|
||||
region: <your-region>
|
||||
bucket: <your-bucket-name>
|
||||
```
|
||||
|
||||
> **注意:**
|
||||
> 1. 使用共享存储(如 NFS、S3、GCS、Azure Blob)时,建议至少部署 2 个及以上 registry 实例,并通过负载均衡(如 keepalived+nginx)实现高可用访问。
|
||||
> 2. 配置共享存储时,需保证各 registry 节点对存储的读写权限和网络连通性。
|
||||
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
|
||||
function createRegistries() {
|
||||
|
||||
# create registry
|
||||
curl -k -u $Harbor_UserPwd -X POST -H "Content-Type: application/json" "https://${Harbor_master1_Address}/api/v2.0/registries" -d "{\"name\": \"master1_2_master2\", \"type\": \"harbor\", \"url\":\"https://${master2_Address}:7443\", \"credential\": {\"access_key\": \"${Harbor_User}\", \"access_secret\": \"${Harbor_Passwd}\"}, \"insecure\": true}"
|
||||
# create registry
|
||||
curl -k -u $Harbor_UserPwd -X POST -H "Content-Type: application/json" "https://${Harbor_master1_Address}/api/v2.0/registries" -d "{\"name\": \"master1_2_master3\", \"type\": \"harbor\", \"url\":\"https://${master3_Address}:7443\", \"credential\": {\"access_key\": \"${Harbor_User}\", \"access_secret\": \"${Harbor_Passwd}\"}, \"insecure\": true}"
|
||||
|
||||
# create registry
|
||||
curl -k -u $Harbor_UserPwd -X POST -H "Content-Type: application/json" "https://${Harbor_master2_Address}/api/v2.0/registries" -d "{\"name\": \"master2_2_master1\", \"type\": \"harbor\", \"url\":\"https://${master1_Address}:7443\", \"credential\": {\"access_key\": \"${Harbor_User}\", \"access_secret\": \"${Harbor_Passwd}\"}, \"insecure\": true}"
|
||||
# create registry
|
||||
curl -k -u $Harbor_UserPwd -X POST -H "Content-Type: application/json" "https://${Harbor_master2_Address}/api/v2.0/registries" -d "{\"name\": \"master2_2_master3\", \"type\": \"harbor\", \"url\":\"https://${master3_Address}:7443\", \"credential\": {\"access_key\": \"${Harbor_User}\", \"access_secret\": \"${Harbor_Passwd}\"}, \"insecure\": true}"
|
||||
|
||||
# create registry
|
||||
curl -k -u $Harbor_UserPwd -X POST -H "Content-Type: application/json" "https://${Harbor_master3_Address}/api/v2.0/registries" -d "{\"name\": \"master3_2_master1\", \"type\": \"harbor\", \"url\":\"https://${master1_Address}:7443\", \"credential\": {\"access_key\": \"${Harbor_User}\", \"access_secret\": \"${Harbor_Passwd}\"}, \"insecure\": true}"
|
||||
# create registry
|
||||
curl -k -u $Harbor_UserPwd -X POST -H "Content-Type: application/json" "https://${Harbor_master3_Address}/api/v2.0/registries" -d "{\"name\": \"master3_2_master2\", \"type\": \"harbor\", \"url\":\"https://${master2_Address}:7443\", \"credential\": {\"access_key\": \"${Harbor_User}\", \"access_secret\": \"${Harbor_Passwd}\"}, \"insecure\": true}"
|
||||
|
||||
}
|
||||
|
||||
function listRegistries() {
|
||||
curl -k -u $Harbor_UserPwd -X GET -H "Content-Type: application/json" "https://${Harbor_master1_Address}/api/v2.0/registries"
|
||||
curl -k -u $Harbor_UserPwd -X GET -H "Content-Type: application/json" "https://${Harbor_master2_Address}/api/v2.0/registries"
|
||||
curl -k -u $Harbor_UserPwd -X GET -H "Content-Type: application/json" "https://${Harbor_master3_Address}/api/v2.0/registries"
|
||||
|
||||
}
|
||||
|
||||
function createReplication() {
|
||||
|
||||
curl -k -u $Harbor_UserPwd -X POST -H "Content-Type: application/json" "https://${Harbor_master1_Address}/api/v2.0/replication/policies" -d "{\"name\": \"master1_2_master2\", \"enabled\": true, \"deletion\":true, \"override\":true, \"replicate_deletion\":true, \"dest_registry\":{ \"id\": 1, \"name\": \"master1_2_master2\"}, \"trigger\": {\"type\": \"event_based\"}, \"dest_namespace_replace_count\":1 }"
|
||||
curl -k -u $Harbor_UserPwd -X POST -H "Content-Type: application/json" "https://${Harbor_master1_Address}/api/v2.0/replication/policies" -d "{\"name\": \"master1_2_master3\", \"enabled\": true, \"deletion\":true, \"override\":true, \"replicate_deletion\":true, \"dest_registry\":{ \"id\": 2, \"name\": \"master1_2_master3\"}, \"trigger\": {\"type\": \"event_based\"}, \"dest_namespace_replace_count\":1 }"
|
||||
|
||||
curl -k -u $Harbor_UserPwd -X POST -H "Content-Type: application/json" "https://${Harbor_master2_Address}/api/v2.0/replication/policies" -d "{\"name\": \"master2_2_master1\", \"enabled\": true, \"deletion\":true, \"override\":true, \"replicate_deletion\":true, \"dest_registry\":{ \"id\": 1, \"name\": \"master2_2_master1\"}, \"trigger\": {\"type\": \"event_based\"}, \"dest_namespace_replace_count\":1 }"
|
||||
curl -k -u $Harbor_UserPwd -X POST -H "Content-Type: application/json" "https://${Harbor_master2_Address}/api/v2.0/replication/policies" -d "{\"name\": \"master2_2_master3\", \"enabled\": true, \"deletion\":true, \"override\":true, \"replicate_deletion\":true, \"dest_registry\":{ \"id\": 2, \"name\": \"master2_2_master3\"}, \"trigger\": {\"type\": \"event_based\"}, \"dest_namespace_replace_count\":1 }"
|
||||
|
||||
curl -k -u $Harbor_UserPwd -X POST -H "Content-Type: application/json" "https://${Harbor_master3_Address}/api/v2.0/replication/policies" -d "{\"name\": \"master3_2_master1\", \"enabled\": true, \"deletion\":true, \"override\":true, \"replicate_deletion\":true, \"dest_registry\":{ \"id\": 1, \"name\": \"master3_2_master1\"}, \"trigger\": {\"type\": \"event_based\"}, \"dest_namespace_replace_count\":1 }"
|
||||
curl -k -u $Harbor_UserPwd -X POST -H "Content-Type: application/json" "https://${Harbor_master3_Address}/api/v2.0/replication/policies" -d "{\"name\": \"master3_2_master2\", \"enabled\": true, \"deletion\":true, \"override\":true, \"replicate_deletion\":true, \"dest_registry\":{ \"id\": 2, \"name\": \"master3_2_master2\"}, \"trigger\": {\"type\": \"event_based\"}, \"dest_namespace_replace_count\":1 }"
|
||||
}
|
||||
|
||||
function listReplications() {
|
||||
|
||||
curl -k -u $Harbor_UserPwd -X GET -H "Content-Type: application/json" "https://${Harbor_master1_Address}/api/v2.0/replication/policies"
|
||||
curl -k -u $Harbor_UserPwd -X GET -H "Content-Type: application/json" "https://${Harbor_master2_Address}/api/v2.0/replication/policies"
|
||||
curl -k -u $Harbor_UserPwd -X GET -H "Content-Type: application/json" "https://${Harbor_master3_Address}/api/v2.0/replication/policies"
|
||||
}
|
||||
|
||||
#### main ######
|
||||
Harbor_master1_Address=master1:7443
|
||||
master1_Address=192.168.122.61
|
||||
Harbor_master2_Address=master2:7443
|
||||
master2_Address=192.168.122.62
|
||||
Harbor_master3_Address=master3:7443
|
||||
master3_Address=192.168.122.63
|
||||
Harbor_User=admin #登录Harbor的用户
|
||||
Harbor_Passwd="Harbor12345" #登录Harbor的用户密码
|
||||
Harbor_UserPwd="$Harbor_User:$Harbor_Passwd"
|
||||
|
||||
|
||||
createRegistries
|
||||
listRegistries
|
||||
createReplication
|
||||
listReplications
|
||||
Loading…
Reference in New Issue