Skip to content
This repository was archived by the owner on Jan 11, 2023. It is now read-only.

Commit e5c3e0b

Browse files
khenidakanhowe
authored andcommitted
Etcd3 Support (#1564)
* Support multiple etcd versions * Modify git ignore and removing keys generated by test * Review fixes * Switching to mirrors * Consider empty version valid on vLabs, gets defaulted in generalized api model * Changed etcd to ver 3.1.10 * unify test etcd version with allowed versions
1 parent c2904e0 commit e5c3e0b

11 files changed

+163
-3
lines changed

.gitignore

+5-1
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,8 @@ test/acs-engine-test/report/TestReport.json
2424
*.swp
2525

2626
# I have no idea why these get generated when I run the e2e test
27-
test/e2e/kubernetes/translations/
27+
test/e2e/kubernetes/translations/
28+
29+
# test outputs
30+
cmd/_test_output
31+

cmd/deploy_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515
const ExampleAPIModel = `{
1616
"apiVersion": "vlabs",
1717
"properties": {
18-
"orchestratorProfile": { "orchestratorType": "Kubernetes", "kubernetesConfig": { "useManagedIdentity": %s } },
18+
"orchestratorProfile": { "orchestratorType": "Kubernetes", "kubernetesConfig": { "useManagedIdentity": %s, "etcdVersion" : "2.5.2" } },
1919
"masterProfile": { "count": 1, "dnsPrefix": "", "vmSize": "Standard_D2_v2" },
2020
"agentPoolProfiles": [ { "name": "linuxpool1", "count": 2, "vmSize": "Standard_D2_v2", "availabilityProfile": "AvailabilitySet" } ],
2121
"windowsProfile": { "adminUsername": "azureuser", "adminPassword": "replacepassword1234$" },

parts/kubernetesmaster-kube-apiserver.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ spec:
3535
- "--oidc-client-id="
3636
- "--oidc-issuer-url="
3737
- "--oidc-username-claim=oid"
38-
- "--storage-backend=etcd2"
38+
- "--storage-backend=<etcdApiVersion>"
3939
- "--v=4"
4040
- "<kubernetesEnableRbac>"
4141
- "--requestheader-allowed-names="

parts/kubernetesmastercustomdata.yml

+53
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#cloud-config
22

33
packages:
4+
{{if not .OrchestratorProfile.IsCustomEtcdVersion}}
45
- etcd
6+
{{end}}
57
- jq
68
- traceroute
79

@@ -292,6 +294,7 @@ write_files:
292294
sed -i "/requestheader-group-headers/d" "/etc/kubernetes/manifests/kube-apiserver.yaml"
293295
sed -i "/requestheader-username-headers/d" "/etc/kubernetes/manifests/kube-apiserver.yaml"
294296
{{end}}
297+
sed -i "s|<etcdApiVersion>|{{ .OrchestratorProfile.GetAPIServerEtcdAPIVersion }}|g" "/etc/kubernetes/manifests/kube-apiserver.yaml"
295298

296299
- path: "/opt/azure/containers/provision.sh"
297300
permissions: "0744"
@@ -307,7 +310,57 @@ write_files:
307310
content: !!binary |
308311
{{WrapAsVariable "mountetcdScript"}}
309312

313+
{{if .OrchestratorProfile.IsCustomEtcdVersion}}
314+
- path: "/etc/systemd/system/etcd.service"
315+
permissions: "0644"
316+
owner: "root"
317+
content: |
318+
[Unit]
319+
Description=etcd - highly-available key value store
320+
Documentation=https://github.com/coreos/etcd
321+
Documentation=man:etcd
322+
After=network.target
323+
Wants=network-online.target
324+
[Service]
325+
Environment=DAEMON_ARGS=
326+
Environment=ETCD_NAME=%H
327+
Environment=ETCD_DATA_DIR=/var/lib/etcd/default
328+
EnvironmentFile=-/etc/default/%p
329+
Type=notify
330+
User=etcd
331+
PermissionsStartOnly=true
332+
ExecStart=/usr/bin/etcd $DAEMON_ARGS
333+
Restart=always
334+
[Install]
335+
WantedBy=multi-user.target
336+
Alias=etcd.service
337+
338+
- path: "/opt/azure/containers/setup-etcd.sh"
339+
permissions: "0744"
340+
owner: "root"
341+
content: |
342+
#!/bin/bash
343+
# if provisioning using any etcd version other than 2.5.2
344+
# We download it and set it up here
345+
set -x
346+
ETCD_VER=v{{ .OrchestratorProfile.KubernetesConfig.EtcdVersion }}
347+
DOWNLOAD_URL=https://acs-mirror.azureedge.net/github-coreos # we use mirror to github
348+
mkdir -p /tmp/etcd-download
349+
curl -L ${DOWNLOAD_URL}/etcd-${ETCD_VER}-linux-amd64.tar.gz -o /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz
350+
tar xzvf /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz -C /usr/bin/ --strip-components=1
351+
#create etcd user
352+
useradd -U "etcd"
353+
usermod -p "$(head -c 32 /dev/urandom | base64)" "etcd"
354+
passwd -u "$etcd" > /dev/null
355+
# update systemctl and start service
356+
systemctl daemon-reload
357+
systemctl enable etcd.service
358+
{{end}}
359+
310360
runcmd:
361+
{{ if .OrchestratorProfile.IsCustomEtcdVersion }}
362+
- /opt/azure/containers/setup-etcd.sh
363+
{{end}}
311364
- apt-mark hold walinuxagent {{GetKubernetesMasterPreprovisionYaml}}
312365
- /bin/echo DAEMON_ARGS=--name "{{WrapAsVerbatim "variables('masterVMNames')[copyIndex(variables('masterOffset'))]"}}" --initial-advertise-peer-urls "{{WrapAsVerbatim "variables('masterEtcdPeerURLs')[copyIndex(variables('masterOffset'))]"}}" --listen-peer-urls "{{WrapAsVerbatim "variables('masterEtcdPeerURLs')[copyIndex(variables('masterOffset'))]"}}" --advertise-client-urls "{{WrapAsVerbatim "variables('masterEtcdClientURLs')[copyIndex(variables('masterOffset'))]"}}" --listen-client-urls "{{WrapAsVerbatim "concat(variables('masterEtcdClientURLs')[copyIndex(variables('masterOffset'))], ',http://127.0.0.1:', variables('masterEtcdClientPort'))"}}" --initial-cluster-token "k8s-etcd-cluster" --initial-cluster "{{WrapAsVerbatim "variables('masterEtcdClusterStates')[div(variables('masterCount'), 2)]"}} --data-dir "/var/lib/etcddisk"" --initial-cluster-state "new" | tee -a /etc/default/etcd
313366
- sudo /bin/chown -R etcd:etcd /var/lib/etcd/default

pkg/acsengine/defaults.go

+6
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,12 @@ func setOrchestratorDefaults(cs *api.ContainerService) {
247247
a.OrchestratorProfile.KubernetesConfig.CloudProviderRateLimitBucket = DefaultKubernetesCloudProviderRateLimitBucket
248248
}
249249
}
250+
251+
// default etcd version
252+
if "" == a.OrchestratorProfile.KubernetesConfig.EtcdVersion {
253+
a.OrchestratorProfile.KubernetesConfig.EtcdVersion = "2.5.2"
254+
}
255+
250256
} else if a.OrchestratorProfile.OrchestratorType == api.DCOS {
251257
if a.OrchestratorProfile.DcosConfig == nil {
252258
a.OrchestratorProfile.DcosConfig = &api.DcosConfig{}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
{
2+
"apiVersion": "vlabs",
3+
"properties": {
4+
"orchestratorProfile": {
5+
"orchestratorType": "Kubernetes",
6+
"kubernetesConfig": {
7+
"etcdVersion": "3.1.10"
8+
}
9+
},
10+
"masterProfile": {
11+
"count": 1,
12+
"dnsPrefix": "masterdns1",
13+
"vmSize": "Standard_D2_v2"
14+
},
15+
"agentPoolProfiles": [
16+
{
17+
"name": "agentpool1",
18+
"count": 3,
19+
"vmSize": "Standard_D2_v2",
20+
"availabilityProfile": "AvailabilitySet"
21+
},
22+
{
23+
"name": "agentpool2",
24+
"count": 3,
25+
"vmSize": "Standard_D2_v2",
26+
"availabilityProfile": "AvailabilitySet"
27+
}
28+
],
29+
"linuxProfile": {
30+
"adminUsername": "azureuser",
31+
"ssh": {
32+
"publicKeys": [
33+
{
34+
"keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm"
35+
}
36+
]
37+
}
38+
},
39+
"servicePrincipalProfile": {
40+
"clientId": "ServicePrincipalClientID",
41+
"secret": "myServicePrincipalClientSecret"
42+
},
43+
"certificateProfile": {
44+
"caCertificate": "caCertificate",
45+
"apiServerCertificate": "apiServerCertificate",
46+
"apiServerPrivateKey": "apiServerPrivateKey",
47+
"clientCertificate": "clientCertificate",
48+
"clientPrivateKey": "clientPrivateKey",
49+
"kubeConfigCertificate": "kubeConfigCertificate",
50+
"kubeConfigPrivateKey": "kubeConfigPrivateKey"
51+
}
52+
}
53+
}

pkg/api/converterfromapi.go

+1
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,7 @@ func convertKubernetesConfigToVLabs(api *KubernetesConfig, vlabs *vlabs.Kubernet
669669
vlabs.EnableAggregatedAPIs = api.EnableAggregatedAPIs
670670
vlabs.GCHighThreshold = api.GCHighThreshold
671671
vlabs.GCLowThreshold = api.GCLowThreshold
672+
vlabs.EtcdVersion = api.EtcdVersion
672673
}
673674

674675
func convertMasterProfileToV20160930(api *MasterProfile, v20160930 *v20160930.MasterProfile) {

pkg/api/convertertoapi.go

+1
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,7 @@ func convertVLabsKubernetesConfig(vlabs *vlabs.KubernetesConfig, api *Kubernetes
616616
api.EnableAggregatedAPIs = vlabs.EnableAggregatedAPIs
617617
api.GCHighThreshold = vlabs.GCHighThreshold
618618
api.GCLowThreshold = vlabs.GCLowThreshold
619+
api.EtcdVersion = vlabs.EtcdVersion
619620
}
620621

621622
func convertV20160930MasterProfile(v20160930 *v20160930.MasterProfile, api *MasterProfile) {

pkg/api/types.go

+17
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/Azure/acs-engine/pkg/api/v20170131"
1010
"github.com/Azure/acs-engine/pkg/api/v20170701"
1111
"github.com/Azure/acs-engine/pkg/api/vlabs"
12+
"github.com/Masterminds/semver"
1213
)
1314

1415
// TypeMeta describes an individual API model object
@@ -185,6 +186,7 @@ type KubernetesConfig struct {
185186
EnableAggregatedAPIs bool `json:"enableAggregatedAPIs,omitempty"`
186187
GCHighThreshold int `json:"gchighthreshold,omitempty"`
187188
GCLowThreshold int `json:"gclowthreshold,omitempty"`
189+
EtcdVersion string `json:"etcdVersion,omitempty"`
188190
}
189191

190192
// DcosConfig Configuration for DC/OS
@@ -533,3 +535,18 @@ func (o *OrchestratorProfile) IsVNETIntegrated() bool {
533535
func (p *Properties) HasAadProfile() bool {
534536
return p.AADProfile != nil
535537
}
538+
539+
// IsCustomEtcdVersion Checks if etcd version is NOT default 2.5.2
540+
func (o *OrchestratorProfile) IsCustomEtcdVersion() bool {
541+
return "2.5.2" != o.KubernetesConfig.EtcdVersion
542+
}
543+
544+
// GetAPIServerEtcdAPIVersion Used to set apiserver's etcdapi version
545+
func (o *OrchestratorProfile) GetAPIServerEtcdAPIVersion() string {
546+
// if we are here, version has already been validated..
547+
etcdversion, _ := semver.NewVersion(o.KubernetesConfig.EtcdVersion)
548+
if 2 == etcdversion.Major() {
549+
return "etcd2"
550+
}
551+
return "etcd3"
552+
}

pkg/api/vlabs/types.go

+1
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ type KubernetesConfig struct {
204204
EnableAggregatedAPIs bool `json:"enableAggregatedAPIs,omitempty"`
205205
GCHighThreshold int `json:"gchighthreshold,omitempty"`
206206
GCLowThreshold int `json:"gclowthreshold,omitempty"`
207+
EtcdVersion string `json:"etcdVersion,omitempty"`
207208
}
208209

209210
// DcosConfig Configuration for DC/OS

pkg/api/vlabs/validate.go

+24
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,32 @@ import (
1616
var (
1717
validate *validator.Validate
1818
keyvaultIDRegex *regexp.Regexp
19+
// Any version has to be mirrored in https://acs-mirror.azureedge.net/github-coreos/etcd-v[Version]-linux-amd64.tar.gz
20+
etcdValidVersions = [...]string{"2.5.2", "3.1.10"}
1921
)
2022

2123
func init() {
2224
validate = validator.New()
2325
keyvaultIDRegex = regexp.MustCompile(`^/subscriptions/\S+/resourceGroups/\S+/providers/Microsoft.KeyVault/vaults/[^/\s]+$`)
2426
}
2527

28+
func isValidEtcdVersion(etcdVersion string) error {
29+
// Empty versions is defaulted to 2.5.2 on the generalized api model
30+
// after vlabs validation. Empty "" version is a valid version for etcd
31+
if "" == etcdVersion {
32+
return nil
33+
}
34+
// We have a version set by user
35+
validVersions := "" // a bag of valid versions
36+
for _, ver := range etcdValidVersions {
37+
if ver == etcdVersion {
38+
return nil
39+
}
40+
validVersions = fmt.Sprintf("%s %s", validVersions, ver)
41+
}
42+
return fmt.Errorf("Invalid etcd version(%s), valid versions are%s", etcdVersion, validVersions)
43+
}
44+
2645
// Validate implements APIObject
2746
func (o *OrchestratorProfile) Validate() error {
2847
// Don't need to call validate.Struct(o)
@@ -498,6 +517,11 @@ func (a *KubernetesConfig) Validate(k8sVersion string) error {
498517
}
499518
}
500519

520+
// Validate that we have a valid etcd version
521+
if e := isValidEtcdVersion(a.EtcdVersion); e != nil {
522+
return e
523+
}
524+
501525
return nil
502526
}
503527

0 commit comments

Comments
 (0)