1use std::io::{self, Error, ErrorKind};
2
3use crate::ec2::{ArchType, OsType};
4
5pub fn start(os_type: OsType) -> io::Result<String> {
6 match os_type {
7 OsType::Ubuntu2004 | OsType::Ubuntu2204 => Ok("#!/usr/bin/env bash
8
9# print all executed commands to terminal
10set -x
11
12# do not mask errors in a pipeline
13set -o pipefail
14
15# treat unset variables as an error
16set -o nounset
17
18# exit script whenever it errs
19set -o errexit
20
21# makes the default answers be used for all questions
22export DEBIAN_FRONTEND=noninteractive
23
24############################################
25### Machine Architecture ###################
26############################################
27# https://github.com/awslabs/amazon-eks-ami/blob/master/scripts/install-worker.sh
28# 'dpkg --print-architecture' to decide amd64/arm64
29# 'uname -m' to decide x86_64/aarch64
30
31MACHINE=$(uname -m)
32if [ \"$MACHINE\" == \"x86_64\" ]; then
33 ARCH=\"amd64\"
34elif [ \"$MACHINE\" == \"aarch64\" ]; then
35 ARCH=\"arm64\"
36else
37 echo \"Unknown machine architecture '$MACHINE'\" >&2
38 exit 1
39fi
40echo MACHINE: $MACHINE
41echo ARCH: $ARCH
42
43# running as root, in /, check CPU/OS/host info
44whoami
45pwd
46lscpu
47cat /etc/os-release
48hostnamectl
49
50############################################
51### Basic packages #########################
52############################################
53
54sudo mkdir -p /etc/systemd/system
55sudo chown -R ubuntu:ubuntu /etc/systemd/system
56
57while [ 1 ]; do
58 sudo apt-get update -yq
59 sudo apt-get upgrade -yq
60 sudo apt-get install -yq \\
61 build-essential tmux git xclip htop zsh \\
62 jq curl wget \\
63 zip unzip gzip tar \\
64 libssl-dev \\
65 pkg-config lsb-release vim \\
66 linux-headers-$(uname -r)
67 sudo apt-get clean
68 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
69 sleep 2s;
70done;
71while [ 1 ]; do
72 sudo apt update
73 sudo apt clean all
74 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
75 sleep 2s;
76done;
77
78# /usr/sbin/iptables
79which iptables
80iptables --version
81
82# /usr/sbin/iptables-save
83which iptables-save
84iptables-save --version
85
86# /usr/sbin/iptables-restore
87which iptables-restore
88iptables-restore --version
89
90/usr/bin/gcc --version
91/usr/bin/c++ -v
92
93if ! command -v lsb_release &> /dev/null
94then
95 echo \"lsb_release could not be found\"
96 exit 1
97fi
98lsb_release --all
99
100# sudo sh -c \"$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)\"
101# chsh -s /bin/zsh
102# sudo chown -R ubuntu /home/ubuntu/.cache
103# sudo chown -R ubuntu /home/ubuntu/.zshrc
104# sudo chown -R ubuntu /home/ubuntu/.zsh_history
105
106mkdir -p /home/ubuntu/.vim
107sudo chown -R ubuntu /home/ubuntu/.vim
108"
109 .to_string()),
110 _ => Err(Error::new(
111 ErrorKind::InvalidInput,
112 format!("os_type '{}' not supported", os_type.as_str()),
113 )),
114 }
115}
116
117pub fn update_bash_profile(
118 os_type: OsType,
119 anaconda_installed: bool,
120 python_installed: bool,
121 rust_installed: bool,
122 cuda_toolkit_installed: bool,
123 go_installed: bool,
124 kubectl_installed: bool,
125 helm_installed: bool,
126 data_directory_mounted: bool,
127) -> io::Result<String> {
128 match os_type {
129 OsType::Ubuntu2004 | OsType::Ubuntu2204 => {
130 let mut paths = Vec::new();
131 if anaconda_installed {
132 paths.push("/home/ubuntu/anaconda3/bin".to_string());
133 }
134 if python_installed {
135 paths.push("/home/ubuntu/.local/bin".to_string());
136 }
137 if rust_installed {
138 paths.push("/home/ubuntu/.cargo/bin".to_string());
139 }
140 if cuda_toolkit_installed {
141 paths.push("/usr/local/cuda-12.2/bin".to_string());
142 }
143
144 let mut profile = String::from(
145 "cat << 'EOF' >> /home/ubuntu/.profile
147HISTSIZE=1000000
148HISTFILESIZE=2000000
149
150alias ..='cd ..'
151alias hh='history | grep'
152alias t=tmux
153alias kill-tmux='tmux list-sessions; tmux kill-session -a;'
154alias kill-docker='docker kill $(docker ps -q)'
155alias clean-docker='docker system prune --all --force; docker rmi $(docker images -a -q);'
156alias pbcopy='xclip -selection clipboard'
157alias gith='git rev-parse HEAD; git rev-parse HEAD | pbcopy'
158
159export VISUAL=vim
160export EDITOR=vim
161export GPG_TTY=$(tty)
162
163",
164 );
165 let mut bashrc = String::from(
166 "cat << 'EOF' >> /home/ubuntu/.bashrc
168HISTSIZE=1000000
169HISTFILESIZE=2000000
170
171alias ..='cd ..'
172alias hh='history | grep'
173alias t=tmux
174alias kill-tmux='tmux list-sessions; tmux kill-session -a;'
175alias kill-docker='docker kill $(docker ps -q)'
176alias clean-docker='docker system prune --all --force; docker rmi $(docker images -a -q);'
177alias pbcopy='xclip -selection clipboard'
178alias gith='git rev-parse HEAD; git rev-parse HEAD | pbcopy'
179
180export VISUAL=vim
181export EDITOR=vim
182export GPG_TTY=$(tty)
183
184",
185 );
186
187 if go_installed {
188 paths.push("/usr/local/go/bin".to_string());
189 paths.push("/home/ubuntu/go/bin".to_string());
190
191 profile.push_str(
192 "export GOPATH=/home/ubuntu/go
193",
194 );
195 bashrc.push_str(
196 "export GOPATH=/home/ubuntu/go
197",
198 );
199 }
200
201 if kubectl_installed {
202 profile.push_str(
203 "alias k=kubectl
204",
205 );
206 bashrc.push_str(
207 "alias k=kubectl
208",
209 );
210 }
211 if helm_installed {
212 profile.push_str(
213 "alias h=helm
214",
215 );
216 bashrc.push_str(
217 "alias h=helm
218",
219 );
220 }
221
222 let path_line = format!(
223 "export PATH={}:$PATH
224",
225 paths.join(":")
226 );
227
228 profile.push_str(&path_line);
229 if rust_installed {
230 profile.push_str(
232 ". /opt/rust/env
233",
234 )
235 }
236 bashrc.push_str(&path_line);
237 if rust_installed {
238 bashrc.push_str(
240 ". /opt/rust/env
241",
242 )
243 }
244
245 if data_directory_mounted {
248 Ok(format!(
249 "
250###########################
251# setting up user bash profiles
252
253{profile}
254# set permissions
255sudo chown -R $(whoami) /data
256sudo chown -R ubuntu /data
257EOF
258
259{bashrc}
260# set permissions
261sudo chown -R $(whoami) /data
262sudo chown -R ubuntu /data
263EOF
264
265{path_line}"
266 ))
267 } else {
268 Ok(format!(
269 "
270###########################
271# setting up user bash profiles
272
273{profile}
274EOF
275
276{bashrc}
277EOF
278
279{path_line}"
280 ))
281 }
282 }
283 _ => Err(Error::new(
284 ErrorKind::InvalidInput,
285 format!("os_type '{}' not supported", os_type.as_str()),
286 )),
287 }
288}
289
290pub fn imds(os_type: OsType) -> io::Result<String> {
291 match os_type {
292 OsType::Ubuntu2004 | OsType::Ubuntu2204 | OsType::Al2023 => Ok("
293###########################
294# install imds utils
295# https://github.com/awslabs/amazon-eks-ami/blob/master/scripts/install-worker.sh
296# https://github.com/awslabs/amazon-eks-ami/tree/master/files/bin
297
298while [ 1 ]; do
299 rm -f /tmp/imds || true;
300 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://raw.githubusercontent.com/awslabs/amazon-eks-ami/master/files/bin/imds\"
301 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
302 sleep 2s;
303done;
304
305chmod +x /tmp/imds
306sudo mv /tmp/imds /usr/bin/imds
307"
308 .to_string()),
309 _ => Err(Error::new(
310 ErrorKind::InvalidInput,
311 format!("os_type '{}' not supported", os_type.as_str()),
312 )),
313 }
314}
315
316pub fn provider_id(os_type: OsType) -> io::Result<String> {
317 match os_type {
318 OsType::Ubuntu2004 | OsType::Ubuntu2204 | OsType::Al2023 => Ok("
319###########################
320# install provider-id utils
321# https://github.com/awslabs/amazon-eks-ami/blob/master/scripts/install-worker.sh
322# https://github.com/awslabs/amazon-eks-ami/tree/master/files/bin
323
324while [ 1 ]; do
325 rm -f /tmp/provider-id || true;
326 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://raw.githubusercontent.com/awslabs/amazon-eks-ami/master/files/bin/provider-id\"
327 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
328 sleep 2s;
329done;
330
331chmod +x /tmp/provider-id
332sudo mv /tmp/provider-id /usr/bin/provider-id
333"
334 .to_string()),
335 _ => Err(Error::new(
336 ErrorKind::InvalidInput,
337 format!("os_type '{}' not supported", os_type.as_str()),
338 )),
339 }
340}
341
342pub fn vercmp(os_type: OsType) -> io::Result<String> {
343 match os_type {
344 OsType::Ubuntu2004 | OsType::Ubuntu2204 | OsType::Al2023 => Ok("
345###########################
346# install vercmp utils
347# https://github.com/awslabs/amazon-eks-ami/blob/master/scripts/install-worker.sh
348# https://github.com/awslabs/amazon-eks-ami/tree/master/files/bin
349
350while [ 1 ]; do
351 rm -f /tmp/vercmp || true;
352 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://raw.githubusercontent.com/awslabs/amazon-eks-ami/master/files/bin/vercmp\"
353 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
354 sleep 2s;
355done;
356
357chmod +x /tmp/vercmp
358sudo mv /tmp/vercmp /usr/bin/vercmp
359"
360 .to_string()),
361 _ => Err(Error::new(
362 ErrorKind::InvalidInput,
363 format!("os_type '{}' not supported", os_type.as_str()),
364 )),
365 }
366}
367
368pub fn setup_local_disks(os_type: OsType) -> io::Result<String> {
369 match os_type {
370 OsType::Ubuntu2004 | OsType::Ubuntu2204 | OsType::Al2023 => Ok("
371###########################
372# install setup-local-disks utils
373# https://github.com/awslabs/amazon-eks-ami/blob/master/scripts/install-worker.sh
374# https://github.com/awslabs/amazon-eks-ami/tree/master/files/bin
375
376while [ 1 ]; do
377 rm -f /tmp/setup-local-disks || true;
378 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://raw.githubusercontent.com/awslabs/amazon-eks-ami/master/files/bin/setup-local-disks\"
379 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
380 sleep 2s;
381done;
382
383chmod +x /tmp/setup-local-disks
384sudo mv /tmp/setup-local-disks /usr/bin/setup-local-disks
385"
386 .to_string()),
387 _ => Err(Error::new(
388 ErrorKind::InvalidInput,
389 format!("os_type '{}' not supported", os_type.as_str()),
390 )),
391 }
392}
393
394pub fn mount_bpf_fs(os_type: OsType) -> io::Result<String> {
395 match os_type {
396 OsType::Ubuntu2004 | OsType::Ubuntu2204 | OsType::Al2023 => Ok("
397###########################
398# install mount-bpf-fs utils
399# https://github.com/awslabs/amazon-eks-ami/blob/master/scripts/install-worker.sh
400# https://github.com/awslabs/amazon-eks-ami/tree/master/files/bin
401
402while [ 1 ]; do
403 rm -f /tmp/mount-bpf-fs || true;
404 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://raw.githubusercontent.com/awslabs/amazon-eks-ami/master/files/bin/mount-bpf-fs\"
405 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
406 sleep 2s;
407done;
408
409chmod +x /tmp/mount-bpf-fs
410sudo mv /tmp/mount-bpf-fs /usr/bin/mount-bpf-fs
411"
412 .to_string()),
413 _ => Err(Error::new(
414 ErrorKind::InvalidInput,
415 format!("os_type '{}' not supported", os_type.as_str()),
416 )),
417 }
418}
419
420pub fn time_sync(os_type: OsType) -> io::Result<String> {
421 match os_type {
422 OsType::Ubuntu2004 | OsType::Ubuntu2204 => Ok("
423###########################
424# install time sync utils
425
426# https://github.com/awslabs/amazon-eks-ami/tree/master/files/bin/configure-clocksource
427while [ 1 ]; do
428 rm -f /tmp/configure-clocksource || true;
429 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://raw.githubusercontent.com/awslabs/amazon-eks-ami/master/files/bin/configure-clocksource\"
430 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
431 sleep 2s;
432done;
433chmod +x /tmp/configure-clocksource
434sudo mv /tmp/configure-clocksource /usr/bin/configure-clocksource
435
436# https://github.com/awslabs/amazon-eks-ami/commit/056e31f8c7477e893424abce468cb32bbcd1f079#diff-049390d14bc3ea2d7882ff0f108e2802ad9b043336c5fa637e93581d9a7fdfc2
437while [ 1 ]; do
438 rm -f /tmp/configure-clocksource.service || true;
439 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://raw.githubusercontent.com/awslabs/amazon-eks-ami/master/files/configure-clocksource.service\"
440 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
441 sleep 2s;
442done;
443sudo mv /tmp/configure-clocksource.service /etc/systemd/system/configure-clocksource.service
444sudo chown root:root /etc/systemd/system/configure-clocksource.service
445systemctl daemon-reload
446systemctl enable --now configure-clocksource
447"
448 .to_string()),
449 _ => Err(Error::new(
450 ErrorKind::InvalidInput,
451 format!("os_type '{}' not supported", os_type.as_str()),
452 )),
453 }
454}
455
456pub fn system_limit_bump(os_type: OsType) -> io::Result<String> {
457 match os_type {
458 OsType::Ubuntu2004 | OsType::Ubuntu2204 | OsType::Al2023 => Ok("
459###########################
460# bumping up system limits
461# https://github.com/awslabs/amazon-eks-ami/blob/master/scripts/install-worker.sh
462
463echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf
464echo fs.inotify.max_user_instances=8192 | sudo tee -a /etc/sysctl.conf
465echo vm.max_map_count=524288 | sudo tee -a /etc/sysctl.conf
466
467# e.g.,
468# \"Accept error: accept tcp [::]:9650: accept4: too many open files; retrying in 1s\"
469sudo echo \"* hard nofile 1000000\" >> /etc/security/limits.conf
470sudo echo \"* soft nofile 1000000\" >> /etc/security/limits.conf
471sudo sysctl -w fs.file-max=1000000
472sudo sysctl -p
473"
474 .to_string()),
475 _ => Err(Error::new(
476 ErrorKind::InvalidInput,
477 format!("os_type '{}' not supported", os_type.as_str()),
478 )),
479 }
480}
481
482pub fn aws_cli(arch_type: ArchType, os_type: OsType) -> io::Result<String> {
483 match (arch_type, os_type) {
484 (ArchType::Amd64
485 | ArchType::Amd64GpuP4NvidiaTeslaA100
486 | ArchType::Amd64GpuG3NvidiaTeslaM60
487 | ArchType::Amd64GpuG4adRadeon
488 | ArchType::Amd64GpuG5NvidiaA10G, OsType::Ubuntu2004 | OsType::Ubuntu2204) => Ok(
489 "
490###########################
491# install AWS CLI
492# https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html
493
494# 'uname -m' to decide x86_64/aarch64
495while [ 1 ]; do
496 sudo rm -f /tmp/awscli-exe-linux-$(uname -m).zip || true;
497 sudo apt-get update -yq && sudo apt-get install -yq wget unzip && wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue https://awscli.amazonaws.com/awscli-exe-linux-$(uname -m).zip
498 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
499 sleep 2s;
500done;
501
502# 'uname -m' to decide x86_64/aarch64
503unzip /tmp/awscli-exe-linux-$(uname -m).zip && sudo ./aws/install
504/usr/local/bin/aws --version
505
506# /usr/local/bin/aws
507which aws
508
509# AWS CLI SSM session manager
510# https://docs.aws.amazon.com/systems-manager/latest/userguide/install-plugin-debian.html
511# 'uname -m' to decide x86_64/aarch64
512curl https://s3.amazonaws.com/session-manager-downloads/plugin/latest/ubuntu_64bit/session-manager-plugin.deb -o /tmp/session-manager-plugin.deb
513sudo dpkg -i /tmp/session-manager-plugin.deb
514rm -f /tmp/session-manager-plugin.deb
515".to_string()),
516
517 (ArchType::Arm64, OsType::Ubuntu2004 | OsType::Ubuntu2204) => Ok(
518 "
519###########################
520# install AWS CLI
521# https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html
522
523# 'uname -m' to decide x86_64/aarch64
524while [ 1 ]; do
525sudo rm -f /tmp/awscli-exe-linux-$(uname -m).zip || true;
526sudo apt-get update -yq && sudo apt-get install -yq wget unzip && wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue https://awscli.amazonaws.com/awscli-exe-linux-$(uname -m).zip
527if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
528sleep 2s;
529done;
530
531# 'uname -m' to decide x86_64/aarch64
532unzip /tmp/awscli-exe-linux-$(uname -m).zip && sudo ./aws/install
533/usr/local/bin/aws --version
534
535# /usr/local/bin/aws
536which aws
537
538# AWS CLI SSM session manager
539# https://docs.aws.amazon.com/systems-manager/latest/userguide/install-plugin-debian.html
540# 'uname -m' to decide x86_64/aarch64
541curl https://s3.amazonaws.com/session-manager-downloads/plugin/latest/ubuntu_arm64/session-manager-plugin.deb -o /tmp/session-manager-plugin.deb
542sudo dpkg -i /tmp/session-manager-plugin.deb
543rm -f /tmp/session-manager-plugin.deb
544".to_string()),
545
546 _ => Err(Error::new(
547 ErrorKind::InvalidInput,
548 "os_type not supported",
549 )),
550 }
551}
552
553pub fn ssm_agent(os_type: OsType) -> io::Result<String> {
554 match os_type {
555 OsType::Ubuntu2004 | OsType::Ubuntu2204 => Ok(
556 "
557###########################
558# install ssm agent
559# https://docs.aws.amazon.com/systems-manager/latest/userguide/agent-install-ubuntu.html
560
561sudo snap install amazon-ssm-agent --classic
562sudo systemctl enable snap.amazon-ssm-agent.amazon-ssm-agent.service
563sudo systemctl restart snap.amazon-ssm-agent.amazon-ssm-agent.service
564mkdir -p /etc/systemd/system/snap.amazon-ssm-agent.amazon-ssm-agent.service.d
565cat > /tmp/amazon-ssm-agent-10-restart-always.conf << EOF
566[Service]
567Restart=always
568RestartSec=60s
569EOF
570
571sudo mkdir -p /etc/systemd/system/snap.amazon-ssm-agent.amazon-ssm-agent.service.d
572sudo mv /tmp/amazon-ssm-agent-10-restart-always.conf /etc/systemd/system/snap.amazon-ssm-agent.amazon-ssm-agent.service.d/10-restart-always.conf
573sudo systemctl start --no-block snap.amazon-ssm-agent.amazon-ssm-agent.service
574".to_string()),
575 _ => Err(Error::new(
576 ErrorKind::InvalidInput,
577 format!("os_type '{}' not supported", os_type.as_str()),
578 )),
579 }
580}
581
582pub fn cloudwatch_agent(os_type: OsType) -> io::Result<String> {
583 match os_type {
584 OsType::Ubuntu2004 | OsType::Ubuntu2204 => Ok(format!(
585 "
586###########################
587# install cloudwatch agent
588# https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/QuickStartEC2Instance.html
589# 'dpkg --print-architecture' to decide amd64/arm64
590
591while [ 1 ]; do
592 rm -f /tmp/amazon-cloudwatch-agent.deb || true;
593 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/$(dpkg --print-architecture)/latest/amazon-cloudwatch-agent.deb\"
594 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
595 sleep 2s;
596done;
597while [ 1 ]; do
598 sudo dpkg -i -E /tmp/amazon-cloudwatch-agent.deb
599 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
600 sleep 2s;
601done;
602"
603 )),
604 _ => Err(Error::new(
605 ErrorKind::InvalidInput,
606 format!("os_type '{}' not supported", os_type.as_str()),
607 )),
608 }
609}
610
611pub fn static_volume_provisioner(
612 os_type: OsType,
613 id: &str,
614 region: &str,
615 volume_type: &str,
616 volume_size: u32,
617 volume_iops: u32,
618 volume_throughput: u32,
619 ebs_device_name: &str,
620 provisioner_initial_wait_random_seconds: usize,
621) -> io::Result<String> {
622 match os_type {
623 OsType::Ubuntu2004 | OsType::Ubuntu2204 => Ok(format!(
624 "
625###########################
626# install aws-volume-manager for x86_64 (mac, linux x86), arm64 (M*), aarch64 (graviton)
627# https://github.com/ava-labs/volume-manager/releases
628
629# 'uname -m' to decide x86_64/aarch64
630while [ 1 ]; do
631 rm -f /tmp/aws-volume-provisioner.$(uname -m)-{os_type}-linux-gnu || true;
632 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://github.com/ava-labs/volume-manager/releases/download/latest/aws-volume-provisioner.$(uname -m)-{os_type}-linux-gnu\"
633 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
634 sleep 2s;
635done;
636
637chmod +x /tmp/aws-volume-provisioner.$(uname -m)-{os_type}-linux-gnu
638/tmp/aws-volume-provisioner.$(uname -m)-{os_type}-linux-gnu --version
639
640/tmp/aws-volume-provisioner.$(uname -m)-{os_type}-linux-gnu \\
641--log-level=info \\
642--region {region} \\
643--initial-wait-random-seconds={provisioner_initial_wait_random_seconds} \\
644--id-tag-key=Id \\
645--id-tag-value={id} \\
646--kind-tag-key=Kind \\
647--kind-tag-value=aws-volume-provisioner \\
648--ec2-tag-asg-name-key=ASG_NAME \\
649--asg-tag-key=autoscaling:groupName \\
650--volume-type={volume_type} \\
651--volume-size={volume_size} \\
652--volume-iops={volume_iops} \\
653--volume-throughput={volume_throughput} \\
654--ebs-device-name={ebs_device_name} \\
655--block-device-name=/dev/nvme1n1 \\
656--filesystem-name=ext4 \\
657--mount-directory-path=/data
658
659# set permissions
660sudo chown -R $(whoami) /data
661sudo chown -R ubuntu /data
662",
663 os_type = os_type.as_str(),
664 id=id,
665 region=region,
666 volume_type=volume_type,
667 volume_size=volume_size,
668 volume_iops=volume_iops,
669 volume_throughput=volume_throughput,
670 ebs_device_name=ebs_device_name,
671 provisioner_initial_wait_random_seconds=provisioner_initial_wait_random_seconds,
672 )),
673 _ => Err(Error::new(
674 ErrorKind::InvalidInput,
675 format!("os_type '{}' not supported", os_type.as_str()),
676 )),
677 }
678}
679
680pub fn static_ip_provisioner(
681 os_type: OsType,
682 id: &str,
683 region: &str,
684 provisioner_initial_wait_random_seconds: usize,
685) -> io::Result<String> {
686 match os_type {
687 OsType::Ubuntu2004 | OsType::Ubuntu2204 => Ok(format!(
688 "
689###########################
690# install aws-ip-manager for x86_64 (mac, linux x86), arm64 (M*), aarch64 (graviton)
691# https://github.com/ava-labs/ip-manager/releases
692
693# 'uname -m' to decide x86_64/aarch64
694while [ 1 ]; do
695 rm -f /tmp/aws-ip-provisioner.$(uname -m)-{os_type}-linux-gnu || true;
696 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://github.com/ava-labs/ip-manager/releases/download/latest/aws-ip-provisioner.$(uname -m)-{os_type}-linux-gnu\"
697 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
698 sleep 2s;
699done;
700
701chmod +x /tmp/aws-ip-provisioner.$(uname -m)-{os_type}-linux-gnu
702/tmp/aws-ip-provisioner.$(uname -m)-{os_type}-linux-gnu --version
703
704/tmp/aws-ip-provisioner.$(uname -m)-{os_type}-linux-gnu \\
705--log-level=info \\
706--region {region} \\
707--initial-wait-random-seconds={provisioner_initial_wait_random_seconds} \\
708--id-tag-key=Id \\
709--id-tag-value={id} \\
710--kind-tag-key=Kind \\
711--kind-tag-value=aws-ip-provisioner \\
712--ec2-tag-asg-name-key=ASG_NAME \\
713--asg-tag-key=autoscaling:groupName \\
714--mounted-eip-file-path=/data/eip.yaml
715",
716 os_type = os_type.as_str(),
717 id=id,
718 region=region,
719 provisioner_initial_wait_random_seconds=provisioner_initial_wait_random_seconds,
720 )),
721 _ => Err(Error::new(
722 ErrorKind::InvalidInput,
723 format!("os_type '{}' not supported", os_type.as_str()),
724 )),
725 }
726}
727
728pub fn anaconda(os_type: OsType) -> io::Result<String> {
729 match os_type {
730 OsType::Ubuntu2004 | OsType::Ubuntu2204 => Ok("
732###########################
733# install anaconda
734# https://docs.conda.io/projects/conda/en/latest/user-guide/install/linux.html
735# https://www.anaconda.com/download#downloads
736
737wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://repo.anaconda.com/archive/Anaconda3-2023.03-1-Linux-$(uname -m).sh\"
738
739# batch mode to not interrupt
740# 'uname -m' to decide x86_64/aarch64
741export PREFIX=/home/ubuntu/anaconda3
742PREFIX=/home/ubuntu/anaconda3 HOME=/home/ubuntu sh /tmp/Anaconda3-2023.03-1-Linux-$(uname -m).sh -b || true
743rm -f /tmp/Anaconda3-2023.03-1-Linux-$(uname -m).sh
744
745# conda update conda -y
746# /home/ubuntu/anaconda3/bin/conda
747
748sudo chown -R ubuntu /home/ubuntu/anaconda3/pkgs || true
749sudo chown -R ubuntu /home/ubuntu/.conda/pkgs || true
750sudo chown -R ubuntu /home/ubuntu/anaconda3/envs || true
751sudo chown -R ubuntu /home/ubuntu/.conda/envs || true
752sudo chown -R ubuntu /home/ubuntu/anaconda3/etc/conda || true
753sudo chown -R ubuntu /home/ubuntu/anaconda3 || true
754
755# check versions
756which conda
757/home/ubuntu/anaconda3/bin/conda --version
758
759# check default system versions
760which python3
761python3 --version
762which python
763python --version
764which pip3
765pip3 --version
766which pip
767pip --version
768
769# check versions from conda
770/home/ubuntu/anaconda3/bin/python3 --version
771/home/ubuntu/anaconda3/bin/python --version
772/home/ubuntu/anaconda3/bin/pip3 --version
773/home/ubuntu/anaconda3/bin/pip --version
774".to_string()),
775 _ => Err(Error::new(
776 ErrorKind::InvalidInput,
777 format!("os_type '{}' not supported", os_type.as_str()),
778 )),
779 }
780}
781
782pub fn python(os_type: OsType) -> io::Result<String> {
783 match os_type {
784 OsType::Ubuntu2004 | OsType::Ubuntu2204 => Ok("
785###########################
786# install python
787
788sudo apt-get install -yq python3-pip
789sudo apt install -yq python-is-python3
790
791# /usr/bin/python3
792which python3
793python3 --version
794
795# /usr/bin/python
796which python
797python --version
798
799pip3 install --upgrade pip
800
801# /usr/local/bin/pip3
802which pip3
803pip3 --version
804
805# /usr/local/bin/pip
806which pip
807pip --version
808"
809 .to_string()),
810 _ => Err(Error::new(
811 ErrorKind::InvalidInput,
812 format!("os_type '{}' not supported", os_type.as_str()),
813 )),
814 }
815}
816
817pub fn rust(os_type: OsType) -> io::Result<String> {
818 match os_type {
819 OsType::Ubuntu2004 | OsType::Ubuntu2204 => {
820 Ok("
821###########################
822# install rust
823# https://www.rust-lang.org/tools/install
824
825export RUSTUP_HOME=/opt/rust
826export CARGO_HOME=/opt/rust
827sudo mkdir -p /opt/rust
828sudo chown -R ubuntu /opt/rust || true
829sudo curl --proto '=https' --tlsv1.2 -sSf --retry 70 --retry-delay 1 https://sh.rustup.rs | bash -s -- -y --no-modify-path --default-toolchain stable --profile default
830sudo -H -u ubuntu bash -c 'source /opt/rust/env && rustup default stable'
831
832. /opt/rust/env
833
834# /opt/rust/bin/rustc
835which rustc
836rustc --version
837".to_string())
838 }
839
840 OsType::Al2023 => {
841 Ok("
842###########################
843# install rust
844# https://www.rust-lang.org/tools/install
845
846export RUSTUP_HOME=/opt/rust
847export CARGO_HOME=/opt/rust
848curl --proto '=https' --tlsv1.2 -sSf --retry 70 --retry-delay 1 https://sh.rustup.rs | bash -s -- -y --no-modify-path --default-toolchain stable --profile default
849sudo -H -u ec2-user bash -c 'source /opt/rust/env && rustup default stable'
850
851. /opt/rust/env
852
853# /opt/rust/bin/rustc
854which rustc
855rustc --version
856".to_string())
857 }
858
859 _ => {
860 Err(Error::new(
861 ErrorKind::InvalidInput,
862 format!("os_type '{}' not supported", os_type.as_str()),
863 ))
864 }
865 }
866}
867
868pub fn go(os_type: OsType) -> io::Result<String> {
869 match os_type {
870 OsType::Ubuntu2004 | OsType::Ubuntu2204 => {
871 Ok("
872###########################
873# install go for amd64 or arm64
874# https://go.dev/dl
875# 'dpkg --print-architecture' to decide amd64/arm64
876
877# sudo rm -rf /usr/local/go
878# sudo curl -s --retry 70 --retry-delay 1 https://storage.googleapis.com/golang/go1.20.7.linux-$(dpkg --print-architecture).tar.gz | sudo tar -C /usr/local/ -xz
879wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://go.dev/dl/go1.20.7.linux-$(dpkg --print-architecture).tar.gz\"
880rm -rf /usr/local/go && tar -C /usr/local -xzf /tmp/go1.20.7.linux-$(dpkg --print-architecture).tar.gz
881
882/usr/local/go/bin/go version
883go version || true
884".to_string())
885 }
886 _ => Err(Error::new(
887 ErrorKind::InvalidInput,
888 format!("os_type '{}' not supported", os_type.as_str()),
889 )),
890 }
891}
892
893pub fn docker(os_type: OsType) -> io::Result<String> {
894 match os_type {
895 OsType::Ubuntu2004 | OsType::Ubuntu2204 => Ok(
896 "
897###########################
898# install docker
899# 'dpkg --print-architecture' to decide amd64/arm64
900# 'lsb_release -cs' to decide jammy/focal/*
901
902if ! command -v lsb_release &> /dev/null
903then
904 echo \"lsb_release could not be found\"
905 exit 1
906fi
907
908while [ 1 ]; do
909 sudo apt-get install -yq ca-certificates gnupg
910 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
911 sleep 2s;
912done;
913while [ 1 ]; do
914 sudo rm -f /usr/share/keyrings/docker-archive-keyring.gpg && curl -fsSL --retry 70 --retry-delay 1 https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
915 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
916 sleep 2s;
917done;
918echo \"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \\
919 $(lsb_release -cs) stable\" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
920while [ 1 ]; do
921 sudo apt-get update -y && sudo apt-get install -yq docker-ce docker-ce-cli containerd.io docker-compose-plugin
922 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
923 sleep 2s;
924done;
925
926sudo systemctl enable docker
927
928sudo usermod -aG docker ubuntu
929
930sudo newgrp docker
931sudo systemctl start docker.service
932sudo systemctl enable --now docker
933sudo docker ps
934sudo docker version
935
936# /usr/bin/containerd
937which containerd
938containerd --version
939
940# /usr/bin/ctr
941which ctr
942ctr --version || true
943ctr version || true
944
945# /usr/bin/docker
946which docker
947docker ps
948docker version
949".to_string()),
950 _ => Err(Error::new(
951 ErrorKind::InvalidInput,
952 format!("os_type '{}' not supported", os_type.as_str()),
953 )),
954 }
955}
956
957pub fn containerd(os_type: OsType) -> io::Result<String> {
958 match os_type {
959 OsType::Ubuntu2004 | OsType::Ubuntu2204 => {
960 Ok("
961###########################
962# install containerd
963# https://containerd.io/downloads/
964# 'dpkg --print-architecture' to decide amd64/arm64
965
966# /usr/bin/containerd
967which containerd || true
968containerd --version || true
969
970while [ 1 ]; do
971 export CONTAINERD_CURRENT_VERSION=$(curl -Ls --retry 70 --retry-delay 1 https://api.github.com/repos/containerd/containerd/releases/latest | grep 'tag_name' | cut -d'v' -f2 | cut -d'\"' -f1)
972 rm -f /tmp/containerd-${CONTAINERD_CURRENT_VERSION}-linux-$(dpkg --print-architecture).tar.gz || true;
973 rm -rf /tmp/containerd || true;
974 mkdir -p /tmp/containerd
975 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://github.com/containerd/containerd/releases/download/v${CONTAINERD_CURRENT_VERSION}/containerd-${CONTAINERD_CURRENT_VERSION}-linux-$(dpkg --print-architecture).tar.gz\" -O - | tar -xzv -C /tmp/containerd
976 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
977 sleep 2s;
978done;
979
980chmod +x /tmp/containerd/bin/*
981sudo mv /tmp/containerd/bin/* /usr/bin/
982rm -rf /tmp/containerd
983
984# /usr/bin/containerd
985which containerd
986containerd --version
987
988# /usr/bin/ctr
989which ctr
990ctr --version || true
991ctr version || true
992".to_string())
993 }
994 _ => {
995 Err(Error::new(
996 ErrorKind::InvalidInput,
997 format!("os_type '{}' not supported", os_type.as_str()),
998 ))
999 }
1000 }
1001}
1002
1003pub fn runc(os_type: OsType) -> io::Result<String> {
1004 match os_type {
1005 OsType::Ubuntu2004 | OsType::Ubuntu2204 => Ok("
1006###########################
1007# install runc
1008# https://github.com/opencontainers/runc
1009# 'dpkg --print-architecture' to decide amd64/arm64
1010
1011which runc || true
1012runc --version || true
1013
1014# this removes \"containerd.io docker-ce\"
1015# sudo apt-get install -yq runc
1016
1017sudo apt-get install -yq libseccomp-dev
1018
1019# rm -rf /tmp/runc
1020# git clone https://github.com/opencontainers/runc /tmp/runc
1021# cd /tmp/runc
1022# make
1023# sudo make install
1024
1025while [ 1 ]; do
1026 export RUNC_CURRENT_VERSION=$(curl -Ls --retry 70 --retry-delay 1 https://api.github.com/repos/opencontainers/runc/releases/latest | grep 'tag_name' | cut -d'v' -f2 | cut -d'\"' -f1)
1027 rm -f /tmp/runc.$(dpkg --print-architecture) || true;
1028 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://github.com/opencontainers/runc/releases/download/v${RUNC_CURRENT_VERSION}/runc.$(dpkg --print-architecture)\"
1029 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
1030 sleep 2s;
1031done;
1032
1033chmod +x /tmp/runc.$(dpkg --print-architecture)
1034sudo mv /tmp/runc.$(dpkg --print-architecture) /usr/bin/runc
1035
1036# /usr/bin/runc
1037which runc
1038runc --version
1039"
1040 .to_string()),
1041 _ => Err(Error::new(
1042 ErrorKind::InvalidInput,
1043 format!("os_type '{}' not supported", os_type.as_str()),
1044 )),
1045 }
1046}
1047
1048pub fn cni_plugins(os_type: OsType) -> io::Result<String> {
1049 match os_type {
1050 OsType::Ubuntu2004 | OsType::Ubuntu2204 | OsType::Al2023 => Ok("
1051###########################
1052# install CNI plugins
1053# https://github.com/containernetworking/plugins
1054# https://github.com/awslabs/amazon-eks-ami/blob/master/scripts/install-worker.sh
1055# 'dpkg --print-architecture' to decide amd64/arm64
1056
1057while [ 1 ]; do
1058 export CNI_PLUGIN_CURRENT_VERSION=$(curl -Ls --retry 70 --retry-delay 1 https://api.github.com/repos/containernetworking/plugins/releases/latest | grep 'tag_name' | cut -d'v' -f2 | cut -d'\"' -f1)
1059 rm -f /tmp/cni-plugins-linux-$(dpkg --print-architecture)-v${CNI_PLUGIN_CURRENT_VERSION}.tgz || true;
1060 rm -rf /tmp/cni-plugins-linux-$(dpkg --print-architecture)-v${CNI_PLUGIN_CURRENT_VERSION} || true;
1061 rm -rf /tmp/cni-plugins || true;
1062 mkdir -p /tmp/cni-plugins
1063 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://github.com/containernetworking/plugins/releases/download/v${CNI_PLUGIN_CURRENT_VERSION}/cni-plugins-linux-$(dpkg --print-architecture)-v${CNI_PLUGIN_CURRENT_VERSION}.tgz\" -O - | tar -xzv -C /tmp/cni-plugins
1064 rm -f /tmp/cni-plugins-linux-$(dpkg --print-architecture)-v${CNI_PLUGIN_CURRENT_VERSION}.tgz || true;
1065 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
1066 sleep 2s;
1067done;
1068
1069ls -lah /tmp/cni-plugins
1070chmod +x /tmp/cni-plugins/*
1071
1072sudo mkdir -p /opt/cni/bin
1073sudo mv /tmp/cni-plugins/* /opt/cni/bin/
1074rm -rf /tmp/cni-plugins
1075
1076sudo find /opt/cni/bin/
1077"
1078 .to_string()),
1079 _ => Err(Error::new(
1080 ErrorKind::InvalidInput,
1081 format!("os_type '{}' not supported", os_type.as_str()),
1082 )),
1083 }
1084}
1085
1086pub fn protobuf_compiler(os_type: OsType) -> io::Result<String> {
1087 match os_type {
1088 OsType::Ubuntu2004 | OsType::Ubuntu2204 => Ok("
1089###########################
1090# install protobuf-compiler
1091
1092sudo apt-get install -yq protobuf-compiler
1093"
1094 .to_string()),
1095 _ => Err(Error::new(
1096 ErrorKind::InvalidInput,
1097 format!("os_type '{}' not supported", os_type.as_str()),
1098 )),
1099 }
1100}
1101
1102pub fn aws_cfn_helper(os_type: OsType, python_pip_bin_path: &str) -> io::Result<String> {
1103 match os_type {
1104 OsType::Ubuntu2004 | OsType::Ubuntu2204 => Ok(format!("
1105###########################
1106# install aws-cfn-bootstrap and other helpers
1107# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-helper-scripts-reference.html
1108# https://repost.aws/knowledge-center/install-cloudformation-scripts
1109
1110# install for root
1111while [ 1 ]; do
1112 pip3 install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz
1113 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
1114 sleep 2s;
1115done;
1116
1117# pip3 install --user aws-cfn-bootstrap doesn't work
1118# pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz
1119# install for user
1120while [ 1 ]; do
1121 sudo -H -u ubuntu bash -c '{python_pip_bin_path}/pip3 install --user https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz'
1122 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
1123 sleep 2s;
1124done;
1125
1126# /home/ubuntu/.local/bin/cfn-hup
1127which cfn-hup
1128cfn-hup --help
1129
1130# sudo /sbin/service cfn-hup restart
1131# sudo ln -s /home/ubuntu/.local/bin/cfn-hup /etc/init.d/cfn-hup
1132# update-rc.d cfn-hup defaults
1133#
1134# sudo systemctl daemon-reload
1135# sudo systemctl status cfn-hup
1136"
1137 )),
1138 _ => Err(Error::new(
1139 ErrorKind::InvalidInput,
1140 format!("os_type '{}' not supported", os_type.as_str()),
1141 )),
1142 }
1143}
1144
1145pub fn saml2aws(os_type: OsType) -> io::Result<String> {
1146 match os_type {
1147 OsType::Ubuntu2004 | OsType::Ubuntu2204 => {
1148 Ok("
1149###########################
1150# install saml2aws
1151# https://api.github.com/repos/Versent/saml2aws/releases/latest
1152# 'dpkg --print-architecture' to decide amd64/arm64
1153
1154while [ 1 ]; do
1155 export SAML2AWS_CURRENT_VERSION=$(curl -Ls --retry 70 --retry-delay 1 https://api.github.com/repos/Versent/saml2aws/releases/latest | grep 'tag_name' | cut -d'v' -f2 | cut -d'\"' -f1)
1156 rm -f /tmp/saml2aws_${SAML2AWS_CURRENT_VERSION}_linux_$(dpkg --print-architecture).tar.gz || true;
1157 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://github.com/Versent/saml2aws/releases/download/v${SAML2AWS_CURRENT_VERSION}/saml2aws_${SAML2AWS_CURRENT_VERSION}_linux_$(dpkg --print-architecture).tar.gz\" -O - | tar -xzv -C /tmp
1158 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
1159 sleep 2s;
1160done;
1161
1162chmod +x /tmp/saml2aws
1163sudo mv /tmp/saml2aws /usr/bin/saml2aws
1164
1165saml2aws --version
1166".to_string())
1167 }
1168 _ => {
1169 Err(Error::new(
1170 ErrorKind::InvalidInput,
1171 format!("os_type '{}' not supported", os_type.as_str()),
1172 ))
1173 }
1174 }
1175}
1176
1177pub fn aws_iam_authenticator(os_type: OsType) -> io::Result<String> {
1178 match os_type {
1179 OsType::Ubuntu2004 | OsType::Ubuntu2204 | OsType::Al2023 => {
1180 Ok("
1181###########################
1182# install aws-iam-authenticator
1183# https://docs.aws.amazon.com/eks/latest/userguide/install-aws-iam-authenticator.html
1184# 'dpkg --print-architecture' to decide amd64/arm64
1185
1186while [ 1 ]; do
1187 export AWS_IAM_AUTHENTICATOR_CURRENT_VERSION=$(curl -Ls --retry 70 --retry-delay 1 https://api.github.com/repos/kubernetes-sigs/aws-iam-authenticator/releases/latest | grep 'tag_name' | cut -d'v' -f2 | cut -d'\"' -f1)
1188 rm -f /tmp/aws-iam-authenticator_${AWS_IAM_AUTHENTICATOR_CURRENT_VERSION}_linux_$(dpkg --print-architecture) || true;
1189 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://github.com/kubernetes-sigs/aws-iam-authenticator/releases/download/v${AWS_IAM_AUTHENTICATOR_CURRENT_VERSION}/aws-iam-authenticator_${AWS_IAM_AUTHENTICATOR_CURRENT_VERSION}_linux_$(dpkg --print-architecture)\"
1190 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
1191 sleep 2s;
1192done;
1193
1194chmod +x /tmp/aws-iam-authenticator_${AWS_IAM_AUTHENTICATOR_CURRENT_VERSION}_linux_$(dpkg --print-architecture)
1195sudo mv /tmp/aws-iam-authenticator_${AWS_IAM_AUTHENTICATOR_CURRENT_VERSION}_linux_$(dpkg --print-architecture) /usr/bin/aws-iam-authenticator
1196
1197# /usr/bin/aws-iam-authenticator
1198which aws-iam-authenticator
1199aws-iam-authenticator version
1200".to_string())
1201 }
1202 _ => {
1203 Err(Error::new(
1204 ErrorKind::InvalidInput,
1205 format!("os_type '{}' not supported", os_type.as_str()),
1206 ))
1207 }
1208 }
1209}
1210
1211pub fn ecr_credential_helper(os_type: OsType) -> io::Result<String> {
1212 match os_type {
1213 OsType::Ubuntu2004 | OsType::Ubuntu2204 | OsType::Al2023 => Ok("
1214###########################
1215# install ECR credential helper
1216# https://github.com/awslabs/amazon-ecr-credential-helper
1217
1218which docker-credential-ecr-login || true
1219docker-credential-ecr-login version || true
1220
1221while [ 1 ]; do
1222 export ECR_CREDENTIAL_HELPER_CURRENT_VERSION=$(curl -Ls --retry 70 --retry-delay 1 https://api.github.com/repos/awslabs/amazon-ecr-credential-helper/releases/latest | grep 'tag_name' | cut -d'v' -f2 | cut -d'\"' -f1)
1223 rm -f /tmp/aws-iam-authenticator_${ECR_CREDENTIAL_HELPER_CURRENT_VERSION}_linux_$(dpkg --print-architecture) || true;
1224 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://amazon-ecr-credential-helper-releases.s3.us-east-2.amazonaws.com/${ECR_CREDENTIAL_HELPER_CURRENT_VERSION}/linux-$(dpkg --print-architecture)/docker-credential-ecr-login\"
1225 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
1226 sleep 2s;
1227done;
1228
1229chmod +x /tmp/docker-credential-ecr-login
1230sudo mv /tmp/docker-credential-ecr-login /usr/bin/docker-credential-ecr-login
1231
1232# /usr/bin/docker-credential-ecr-login
1233which docker-credential-ecr-login
1234docker-credential-ecr-login version
1235"
1236 .to_string()),
1237 _ => Err(Error::new(
1238 ErrorKind::InvalidInput,
1239 format!("os_type '{}' not supported", os_type.as_str()),
1240 )),
1241 }
1242}
1243
1244pub fn ecr_credential_provider(os_type: OsType) -> io::Result<String> {
1245 match os_type {
1246 OsType::Ubuntu2004 | OsType::Ubuntu2204 => Ok("
1247###########################
1248# install ecr-credential-provider
1249# https://github.com/kubernetes/cloud-provider-aws/tree/master/cmd/ecr-credential-provider
1250# https://github.com/kubernetes/cloud-provider-aws/releases
1251# https://github.com/awslabs/amazon-eks-ami/blob/master/scripts/install-worker.sh
1252
1253if ! command -v go &> /dev/null
1254then
1255 echo \"go could not be found\"
1256 exit 1
1257fi
1258
1259while [ 1 ]; do
1260 HOME=/home/ubuntu GOPATH=/home/ubuntu/go /usr/local/go/bin/go install -v k8s.io/cloud-provider-aws/cmd/ecr-credential-provider@v1.27.1
1261 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
1262 sleep 2s;
1263done;
1264
1265which ecr-credential-provider
1266chmod +x /home/ubuntu/go/bin/ecr-credential-provider
1267sudo cp -v /home/ubuntu/go/bin/ecr-credential-provider /usr/bin/ecr-credential-provider
1268
1269# /usr/bin/ecr-credential-provider
1270which ecr-credential-provider
1271
1272# TODO: this blocks
1273# ecr-credential-provider --help
1274
1275sudo mkdir -p /etc/eks
1276sudo mkdir -p /etc/eks/image-credential-provider
1277
1278sudo cp -v /home/ubuntu/go/bin/ecr-credential-provider /etc/eks/image-credential-provider/ecr-credential-provider
1279
1280while [ 1 ]; do
1281 rm -f /tmp/ecr-credential-provider-config.json || true;
1282 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://raw.githubusercontent.com/awslabs/amazon-eks-ami/master/files/ecr-credential-provider-config.json\"
1283 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
1284 sleep 2s;
1285done;
1286
1287chmod +x /tmp/ecr-credential-provider-config.json
1288sudo mv /tmp/ecr-credential-provider-config.json /etc/eks/image-credential-provider/config.json
1289
1290sudo chown -R root:root /etc/eks
1291sudo chown -R ubuntu:ubuntu /etc/eks
1292find /etc/eks
1293"
1294 .to_string()),
1295 _ => Err(Error::new(
1296 ErrorKind::InvalidInput,
1297 format!("os_type '{}' not supported", os_type.as_str()),
1298 )),
1299 }
1300}
1301
1302pub fn kubelet(os_type: OsType) -> io::Result<String> {
1303 match os_type {
1304 OsType::Ubuntu2004 | OsType::Ubuntu2204 | OsType::Al2023 => {
1305 Ok("
1306###########################
1307# install kubelet
1308# https://kubernetes.io/releases/
1309# https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/
1310# 'dpkg --print-architecture' to decide amd64/arm64
1311
1312while [ 1 ]; do
1313 export K8S_CURRENT_VERSION=$(curl -L -s --retry 70 --retry-delay 1 https://dl.k8s.io/release/stable.txt)
1314 # overwrite with 1.26
1315 export K8S_CURRENT_VERSION=\"v1.26.7\"
1316
1317 rm -f /tmp/kubelet || true;
1318 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://dl.k8s.io/release/${K8S_CURRENT_VERSION}/bin/linux/$(dpkg --print-architecture)/kubelet\"
1319 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
1320 sleep 2s;
1321done;
1322
1323chmod +x /tmp/kubelet
1324sudo mv /tmp/kubelet /usr/bin/kubelet
1325rm -f /tmp/kubelet
1326
1327# /usr/bin/kubelet
1328which kubelet
1329kubelet --version
1330".to_string())
1331 }
1332 _ => {
1333 Err(Error::new(
1334 ErrorKind::InvalidInput,
1335 format!("os_type '{}' not supported", os_type.as_str()),
1336 ))
1337 }
1338 }
1339}
1340
1341pub fn kubectl(os_type: OsType) -> io::Result<String> {
1342 match os_type {
1343 OsType::Ubuntu2004 | OsType::Ubuntu2204 => {
1344 Ok("
1345###########################
1346# install kubectl
1347# https://kubernetes.io/releases/
1348# https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/
1349# 'dpkg --print-architecture' to decide amd64/arm64
1350
1351while [ 1 ]; do
1352 export K8S_CURRENT_VERSION=$(curl -L -s --retry 70 --retry-delay 1 https://dl.k8s.io/release/stable.txt)
1353 # overwrite with 1.26
1354 export K8S_CURRENT_VERSION=\"v1.26.7\"
1355
1356 rm -f /tmp/kubectl || true;
1357 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://dl.k8s.io/release/${K8S_CURRENT_VERSION}/bin/linux/$(dpkg --print-architecture)/kubectl\"
1358 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
1359 sleep 2s;
1360done;
1361
1362chmod +x /tmp/kubectl
1363sudo mv /tmp/kubectl /usr/bin/kubectl
1364rm -f /tmp/kubectl
1365
1366# /usr/bin/kubectl
1367which kubectl
1368kubectl version --client=true
1369".to_string())
1370 }
1371 _ => {
1372 Err(Error::new(
1373 ErrorKind::InvalidInput,
1374 format!("os_type '{}' not supported", os_type.as_str()),
1375 ))
1376 }
1377 }
1378}
1379
1380pub fn helm(os_type: OsType) -> io::Result<String> {
1381 match os_type {
1382 OsType::Ubuntu2004 | OsType::Ubuntu2204 => {
1383 Ok("
1384###########################
1385# install helm
1386# https://helm.sh/docs/intro/install/
1387# 'dpkg --print-architecture' to decide amd64/arm64
1388
1389while [ 1 ]; do
1390 export HELM_CURRENT_VERSION=$(curl -Ls --retry 70 --retry-delay 1 https://api.github.com/repos/helm/helm/releases/latest | grep 'tag_name' | cut -d'v' -f2 | cut -d'\"' -f1)
1391 rm -f /tmp/helm-${HELM_CURRENT_VERSION}-linux-$(dpkg --print-architecture).tar.gz || true;
1392 rm -rf /tmp/helm || true;
1393 mkdir -p /tmp/helm
1394 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://get.helm.sh/helm-v${HELM_CURRENT_VERSION}-linux-$(dpkg --print-architecture).tar.gz\" -O - | tar -xzv -C /tmp/helm
1395 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
1396 sleep 2s;
1397done;
1398
1399chmod +x /tmp/helm/linux-$(dpkg --print-architecture)/helm
1400sudo mv /tmp/helm/linux-$(dpkg --print-architecture)/helm /usr/bin/helm
1401rm -rf /tmp/helm
1402
1403# /usr/bin/helm
1404which helm
1405helm version
1406".to_string())
1407 }
1408 _ => {
1409 Err(Error::new(
1410 ErrorKind::InvalidInput,
1411 format!("os_type '{}' not supported", os_type.as_str()),
1412 ))
1413 }
1414 }
1415}
1416
1417pub fn terraform(os_type: OsType) -> io::Result<String> {
1418 match os_type {
1419 OsType::Ubuntu2004 | OsType::Ubuntu2204 => {
1420 Ok("
1421###########################
1422# install terraform
1423# https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli
1424# 'dpkg --print-architecture' to decide amd64/arm64
1425# 'lsb_release -cs' to decide jammy/focal/*
1426
1427if ! command -v lsb_release &> /dev/null
1428then
1429 echo \"lsb_release could not be found\"
1430 exit 1
1431fi
1432
1433while [ 1 ]; do
1434 sudo apt-get install -yq gnupg software-properties-common
1435 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
1436 sleep 2s;
1437done;
1438while [ 1 ]; do
1439 sudo rm -f /usr/share/keyrings/hashicorp-archive-keyring.gpg && curl -fsSL --retry 70 --retry-delay 1 https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
1440 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
1441 sleep 2s;
1442done;
1443sudo gpg --no-default-keyring --keyring /usr/share/keyrings/hashicorp-archive-keyring.gpg --fingerprint
1444
1445echo \"deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main\" | sudo tee /etc/apt/sources.list.d/hashicorp.list > /dev/null
1446while [ 1 ]; do
1447 sudo apt-get update -y && sudo apt-get install -yq terraform
1448 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
1449 sleep 2s;
1450done;
1451
1452# /usr/bin/terraform
1453which terraform
1454terraform --version
1455".to_string())
1456 }
1457 _ => {
1458 Err(Error::new(
1459 ErrorKind::InvalidInput,
1460 format!("os_type '{}' not supported", os_type.as_str()),
1461 ))
1462 }
1463 }
1464}
1465
1466pub fn ssh_key_with_email(os_type: OsType, email: &str) -> io::Result<String> {
1467 match os_type {
1468 OsType::Ubuntu2004 | OsType::Ubuntu2204 => Ok(format!(
1469 "
1470###########################
1471# create an SSH key
1472
1473# NOTE/SECURITY: this must be deleted when building AMI
1474ssh-keygen -q -t rsa -b 4096 -C \"{email}\" -N '' -f /home/ubuntu/.ssh/id_rsa <<<y >/dev/null 2>&1
1475eval \"$(ssh-agent -s)\"
1476ssh-add /home/ubuntu/.ssh/id_rsa
1477cat /home/ubuntu/.ssh/id_rsa.pub
1478
1479# set permissions
1480sudo chown -R $(whoami) /home/ubuntu/.ssh
1481sudo chown -R ubuntu /home/ubuntu/.ssh
1482",
1483 email = email,
1484 )),
1485 _ => Err(Error::new(
1486 ErrorKind::InvalidInput,
1487 format!("os_type '{}' not supported", os_type.as_str()),
1488 )),
1489 }
1490}
1491
1492pub fn ena(os_type: OsType) -> io::Result<String> {
1496 match &os_type {
1497 OsType::Ubuntu2004 | OsType::Ubuntu2204 => Ok("
1498###########################
1499# enable enhanced networking
1500# https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/enhanced-networking-ena.html#enhanced-networking-ena-ubuntu
1501
1502while [ 1 ]; do
1503 sudo apt-get update && sudo apt-get upgrade -y linux-aws
1504 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
1505 sleep 2s;
1506done;
1507
1508if ! command -v imds &> /dev/null
1509then
1510 echo \"imds could not be found\"
1511 exit 1
1512fi
1513
1514if ! command -v aws &> /dev/null
1515then
1516 echo \"aws could not be found\"
1517 exit 1
1518fi
1519
1520ip link show
1521
1522# https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/enhanced-networking-ena.html#test-enhanced-networking-ena
1523# TODO: this may not work... need pre-installed AMI or restart
1524modinfo ena || true
1525
1526# https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html
1527INSTANCE_ID=$(imds /latest/meta-data/instance-id)
1528REGION=$(imds /latest/dynamic/instance-identity/document | jq .region -r)
1529
1530# must stop the instance first
1531# aws ec2 stop-instances --region ${REGION} --instance-ids ${INSTANCE_ID}
1532#
1533# run this outside of EC2
1534# An error occurred (IncorrectInstanceState) when calling the ModifyInstanceAttribute operation: The instance 'i-05f974ac421d49bc2' is not in the 'stopped' state.
1535aws ec2 modify-instance-attribute --region ${REGION} --instance-id ${INSTANCE_ID} --ena-support || true
1536
1537# expects [ true ]
1538aws ec2 describe-instances --region ${REGION} --instance-ids ${INSTANCE_ID} --query \"Reservations[].Instances[].EnaSupport\"
1539
1540# https://docs.aws.amazon.com/cli/latest/reference/ec2/register-image.html
1541# aws ec2 create-image --region ${REGION} --instance-id ${INSTANCE_ID} --name random-ami-name
1542# aws ec2 register-image --region ${REGION} --ena-support --name random-ami-name
1543
1544# https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/enhanced-networking-ena.html#test-enhanced-networking-ena
1545# TODO: this may not work... need pre-installed AMI or restart
1546ip link show
1547ethtool -i ens5 || true
1548modinfo ena
1549"
1550 .to_string()),
1551
1552 _ => Err(Error::new(
1553 ErrorKind::InvalidInput,
1554 format!("os_type '{}' not supported", os_type.as_str()),
1555 )),
1556 }
1557}
1558
1559pub fn nvidia_driver(arch_type: ArchType, os_type: OsType) -> io::Result<String> {
1560 match (&arch_type, &os_type) {
1561 (ArchType::Amd64GpuG3NvidiaTeslaM60 | ArchType::Amd64GpuG4dnNvidiaT4 | ArchType::Amd64GpuG5NvidiaA10G , OsType::Ubuntu2004) => Ok("
1562###########################
1563# install nvidia driver for ubuntu 20.04
1564# https://www.nvidia.com/Download/index.aspx?lang=en-us
1565# https://docs.nvidia.com/datacenter/tesla/tesla-installation-notes/index.html
1566# https://www.nvidia.com/en-us/drivers/unix/
1567
1568# Release Date: 2021.10.26
1569DRIVER_VERSION=460.106.00
1570BASE_URL=https://us.download.nvidia.com/tesla
1571
1572while [ 1 ]; do
1573 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"${BASE_URL}/${DRIVER_VERSION}/NVIDIA-Linux-$(uname -m)-${DRIVER_VERSION}.run\"
1574 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
1575 sleep 2s;
1576done;
1577
1578# 'uname -m' to decide x86_64/aarch64
1579sudo sh /tmp/NVIDIA-Linux-$(uname -m)-${DRIVER_VERSION}.run --silent --ui=none --no-questions
1580rm -f /tmp/NVIDIA-Linux-$(uname -m)-${DRIVER_VERSION}.run
1581sudo tail /var/log/nvidia-installer.log
1582
1583# check the driver
1584find /usr/lib/modules -name nvidia.ko
1585find /usr/lib/modules -name nvidia.ko -exec modinfo {} \\;
1586
1587if ! command -v nvidia-smi &> /dev/null
1588then
1589 echo \"nvidia-smi could not be found\"
1590 exit 1
1591fi
1592
1593# /usr/bin/nvidia-smi
1594which nvidia-smi
1595nvidia-smi
1596"
1597 .to_string()),
1598
1599 (ArchType::Amd64GpuG3NvidiaTeslaM60 | ArchType::Amd64GpuG4dnNvidiaT4 | ArchType::Amd64GpuG5NvidiaA10G , OsType::Ubuntu2204) => Ok("
1600###########################
1601# install nvidia driver for ubuntu 22.04
1602# https://www.nvidia.com/Download/index.aspx?lang=en-us
1603# https://docs.nvidia.com/datacenter/tesla/tesla-installation-notes/index.html
1604# https://www.nvidia.com/en-us/drivers/unix/
1605
1606# THIS IS DIFFERENT FOR UBUNTU LAPTOP
1607# e.g.,
1608# Release Date: 2023.8.29
1609# DRIVER_VERSION=535.104.05
1610# https://us.download.nvidia.com/XFree86/Linux-x86_64/535.104.05/NVIDIA-Linux-x86_64-535.104.05.run
1611#
1612# in case of rollback
1613# original system76 ubuntu 22.04 ships
1614# DRIVER_VERSION=525.105.17
1615# CUDA_VERSION=12.0
1616
1617# Release Date: 2023.8.29
1618DRIVER_VERSION=535.104.05
1619BASE_URL=https://us.download.nvidia.com/tesla
1620
1621while [ 1 ]; do
1622 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"${BASE_URL}/${DRIVER_VERSION}/NVIDIA-Linux-$(uname -m)-${DRIVER_VERSION}.run\"
1623 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
1624 sleep 2s;
1625done;
1626
1627# 'uname -m' to decide x86_64/aarch64
1628sudo sh /tmp/NVIDIA-Linux-$(uname -m)-${DRIVER_VERSION}.run --silent --ui=none --no-questions
1629rm -f /tmp/NVIDIA-Linux-$(uname -m)-${DRIVER_VERSION}.run
1630tail /var/log/nvidia-installer.log
1631
1632# check the driver
1633find /usr/lib/modules -name nvidia.ko
1634find /usr/lib/modules -name nvidia.ko -exec modinfo {} \\;
1635
1636if ! command -v nvidia-smi &> /dev/null
1637then
1638 echo \"nvidia-smi could not be found\"
1639 exit 1
1640fi
1641
1642# /usr/bin/nvidia-smi
1643which nvidia-smi
1644nvidia-smi
1645"
1646 .to_string()),
1647
1648 _ => Err(Error::new(
1649 ErrorKind::InvalidInput,
1650 format!("arch_type '{}', os_type '{}' not supported", arch_type.as_str(), os_type.as_str()),
1651 )),
1652 }
1653}
1654
1655pub fn nvidia_cuda_toolkit(os_type: OsType) -> io::Result<String> {
1656 match os_type {
1657 OsType::Ubuntu2004 | OsType::Ubuntu2204 => Ok("
1658###########################
1659# install nvidia cuda toolkit
1660# this installs cuda 11 by default on ubuntu 20.04
1661# sudo apt install -yq nvidia-cuda-toolkit
1662# https://developer.nvidia.com/cuda-downloads?target_os=Linux&target_arch=x86_64&Distribution=Ubuntu&target_version=20.04&target_type=runfile_local
1663# https://developer.nvidia.com/cuda-downloads?target_os=Linux&target_arch=x86_64&Distribution=Ubuntu&target_version=22.04&target_type=runfile_local
1664
1665# /cuda-installer: error while loading shared libraries: libxml2.so.2: cannot open shared object file: No such file or directory
1666sudo apt-get install -y libxml2
1667
1668# this upgrades to CUDA Version: 12.2
1669CUDA_VERSION=12.2.2
1670TOOL_KIT_VERSION=535.104.05
1671BASE_URL=https://developer.download.nvidia.com/compute/cuda
1672
1673# add --override-driver-check to overwrite
1674while [ 1 ]; do
1675 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"${BASE_URL}/${CUDA_VERSION}/local_installers/cuda_${CUDA_VERSION}_${TOOL_KIT_VERSION}_linux.run\"
1676 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
1677 sleep 2s;
1678done;
1679
1680sudo sh /tmp/cuda_${CUDA_VERSION}_${TOOL_KIT_VERSION}_linux.run --silent
1681rm -f /tmp/cuda_${CUDA_VERSION}_${TOOL_KIT_VERSION}_linux.run
1682tail /var/log/cuda-installer.log
1683
1684if ! command -v nvcc &> /dev/null
1685then
1686 echo \"nvcc could not be found\"
1687
1688 # PATH env might not been updated yet
1689 # exit 1
1690fi
1691
1692# /usr/local/cuda-12.2/bin
1693which nvcc || true
1694nvcc --version || true
1695/usr/local/cuda-12.2/bin/nvcc --version
1696
1697if ! command -v nvidia-smi &> /dev/null
1698then
1699 echo \"nvidia-smi could not be found\"
1700 exit 1
1701fi
1702
1703# /usr/bin/nvidia-smi
1704which nvidia-smi
1705nvidia-smi
1706"
1707 .to_string()),
1708
1709 _ => Err(Error::new(
1710 ErrorKind::InvalidInput,
1711 format!("os_type '{}' not supported", os_type.as_str()),
1712 )),
1713 }
1714}
1715
1716pub fn nvidia_container_toolkit(os_type: OsType) -> io::Result<String> {
1717 match os_type {
1718 OsType::Ubuntu2004 | OsType::Ubuntu2204 => Ok("
1719###########################
1720# install nvidia container toolkit
1721# https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html
1722
1723distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
1724curl -fsSL --retry 70 --retry-delay 1 https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
1725
1726curl -s -L --retry 70 --retry-delay 1 https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list | \\
1727sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \\
1728sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
1729
1730sudo apt-get update
1731sudo apt-get install -yq nvidia-container-toolkit
1732
1733if ! command -v nvidia-ctk &> /dev/null
1734then
1735 echo \"nvidia-ctk could not be found\"
1736 exit 1
1737fi
1738
1739# /usr/bin/nvidia-ctk
1740which nvidia-ctk
1741nvidia-ctk --version
1742
1743if command -v docker &> /dev/null
1744then
1745 echo \"checking nvidia container toolkit with docker\"
1746 # TODO: support other runtime?
1747 sudo nvidia-ctk runtime configure --runtime=docker
1748
1749 # https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/getting-started.html#install-nvidia-gpu-operator
1750 cat /etc/nvidia-container-runtime/config.toml
1751
1752 # restart docker
1753 sudo systemctl restart docker
1754
1755 # test nvidia container toolkit
1756 sudo docker run --rm --runtime=nvidia --gpus all nvidia/cuda:11.6.2-base-ubuntu20.04 nvidia-smi
1757else
1758 echo \"docker not install -- skip checking 'nvidia-ctk runtime configure'\"
1759fi
1760"
1761 .to_string()),
1762
1763 _ => Err(Error::new(
1764 ErrorKind::InvalidInput,
1765 format!("os_type '{}' not supported", os_type.as_str()),
1766 )),
1767 }
1768}
1769
1770pub fn amd_radeon_gpu_driver(arch_type: ArchType, os_type: OsType) -> io::Result<String> {
1771 match (&arch_type, &os_type) {
1772 (ArchType::Amd64GpuG4adRadeon, OsType::Ubuntu2004 | OsType::Ubuntu2204) => Ok("
1773###########################
1774# install AMD Radeon driver for ubuntu
1775# https://www.amd.com/en/support/kb/faq/amdgpupro-install
1776# https://amdgpu-install.readthedocs.io/en/latest/install-prereq.html#downloading-the-installer-package
1777# https://amdgpu-install.readthedocs.io/en/latest/install-script.html
1778
1779while [ 1 ]; do
1780 sudo apt-get -y install linux-modules-extra-aws
1781 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
1782 sleep 2s;
1783done;
1784
1785DRIVER_VERSION1=5.4
1786DRIVER_VERSION2=5.4.50403-1_all
1787BASE_URL=https://repo.radeon.com
1788
1789while [ 1 ]; do
1790 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"${BASE_URL}/${DRIVER_VERSION1}/ubuntu/$(lsb_release -cs)/amdgpu-install_${DRIVER_VERSION2}.deb\"
1791 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
1792 sleep 2s;
1793done;
1794
1795# 'uname -m' to decide x86_64/aarch64
1796sudo apt-get -y install /tmp/amdgpu-install_${DRIVER_VERSION2}.deb
1797sudo sh /tmp/NVIDIA-Linux-$(uname -m)-${DRIVER_VERSION}.run --silent --ui=none --no-questions
1798
1799if ! command -v amdgpu-install &> /dev/null
1800then
1801 echo \"amdgpu-install could not be found\"
1802 exit 1
1803fi
1804
1805# https://amdgpu-install.readthedocs.io/en/latest/install-script.html
1806sudo amdgpu-install -y --accept-eula --usecase=dkms
1807
1808# /usr/bin/amdgpu-install
1809which amdgpu-install
1810amdgpu-install -h
1811"
1812 .to_string()),
1813
1814 _ => Err(Error::new(
1815 ErrorKind::InvalidInput,
1816 format!("arch_type '{}', os_type '{}' not supported", arch_type.as_str(), os_type.as_str()),
1817 )),
1818 }
1819}
1820
1821pub fn cmake(os_type: OsType, python_pip_bin_path: &str) -> io::Result<String> {
1822 match os_type {
1823 OsType::Ubuntu2004 | OsType::Ubuntu2204 => Ok(format!("
1824###########################
1825# install cmake
1826# https://askubuntu.com/questions/355565/how-do-i-install-the-latest-version-of-cmake-from-the-command-line
1827
1828sudo apt purge --auto-remove cmake
1829
1830# wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | sudo tee /etc/apt/trusted.gpg.d/kitware.gpg >/dev/null
1831# sudo apt-add-repository 'deb https://apt.kitware.com/ubuntu/ focal main'
1832# sudo apt-add-repository 'deb https://apt.kitware.com/ubuntu/ jammy main'
1833# sudo apt update -y
1834# sudo apt install -yq cmake
1835
1836which pip
1837{python_pip_bin_path}/pip install --upgrade cmake
1838
1839which cmake
1840cmake --version
1841")),
1842 _ => Err(Error::new(
1843 ErrorKind::InvalidInput,
1844 format!("os_type '{}' not supported", os_type.as_str()),
1845 )),
1846 }
1847}
1848
1849pub fn dev_bark(
1850 os_type: OsType,
1851 python_pip_bin_path: &str,
1852 data_volume_mounted: bool,
1853) -> io::Result<String> {
1854 match os_type {
1855 OsType::Ubuntu2004 | OsType::Ubuntu2204 => {
1856 let clone_dir = if data_volume_mounted {
1857 String::from("/data")
1858 } else {
1859 String::from("/home/ubuntu")
1860 };
1861 Ok(format!(
1862 "
1863###########################
1864# install bark
1865# https://github.com/suno-ai/bark
1866
1867ls -lah {clone_dir}/
1868git clone https://github.com/suno-ai/bark.git {clone_dir}/bark
1869cd {clone_dir}/bark
1870
1871which python
1872{python_pip_bin_path}/python -m pip install .
1873which pip
1874{python_pip_bin_path}/pip install --verbose nltk
1875"
1876 ))
1877 }
1878 _ => Err(Error::new(
1879 ErrorKind::InvalidInput,
1880 format!("os_type '{}' not supported", os_type.as_str()),
1881 )),
1882 }
1883}
1884
1885pub fn gcc7(os_type: OsType) -> io::Result<String> {
1886 match os_type {
1887 OsType::Ubuntu2004 | OsType::Ubuntu2204 => Ok("
1888###########################
1889# install gcc7
1890# gcc downgrade <8, otherwise faiss 'cmake -B build .' fails with
1891# 138 | #error -- unsupported GNU version! gcc versions later than 8 are not supported!
1892# https://stackoverflow.com/questions/65605972/cmake-unsupported-gnu-version-gcc-versions-later-than-8-are-not-supported
1893
1894sudo apt remove -y gcc
1895sudo apt-get install gcc-7 g++-7 -y
1896sudo ln -s /usr/bin/gcc-7 /usr/bin/gcc
1897sudo ln -s /usr/bin/g++-7 /usr/bin/g++
1898sudo ln -s /usr/bin/gcc-7 /usr/bin/cc
1899sudo ln -s /usr/bin/g++-7 /usr/bin/c++
1900/usr/bin/gcc --version
1901/usr/bin/c++ -v
1902"
1903 .to_string()),
1904 _ => Err(Error::new(
1905 ErrorKind::InvalidInput,
1906 format!("os_type '{}' not supported", os_type.as_str()),
1907 )),
1908 }
1909}
1910
1911pub fn dev_faiss_gpu(os_type: OsType, data_volume_mounted: bool) -> io::Result<String> {
1912 match os_type {
1913 OsType::Ubuntu2004 | OsType::Ubuntu2204 => {
1914 let clone_dir = if data_volume_mounted {
1915 String::from("/data")
1916 } else {
1917 String::from("/home/ubuntu")
1918 };
1919 Ok(format!("
1920###########################
1921# install faiss
1922# https://github.com/facebookresearch/faiss#installing
1923# https://github.com/facebookresearch/faiss/blob/main/INSTALL.md
1924# https://github.com/facebookresearch/faiss/wiki/Troubleshooting
1925
1926# otherwise,
1927# Could NOT find BLAS (missing: BLAS_LIBRARIES)
1928sudo apt-get install -yq libopenblas-dev
1929
1930# otherwise,
1931# Could NOT find SWIG (missing: SWIG_EXECUTABLE SWIG_DIR python)
1932sudo apt-get install -yq swig
1933
1934/usr/bin/gcc --version
1935/usr/bin/c++ -v
1936
1937which cmake
1938cmake --version
1939
1940ls -lah {clone_dir}/
1941git clone https://github.com/facebookresearch/faiss.git {clone_dir}/faiss
1942
1943# generates the system-dependent configuration/build files in the build/ subdirectory
1944# cd {clone_dir}/faiss
1945# cmake -B build .
1946
1947# builds the C++ library
1948# cd {clone_dir}/faiss
1949# make -C build -j faiss
1950
1951# builds the python bindings for Faiss
1952# cd {clone_dir}/faiss
1953# make -C build -j swigfaiss
1954
1955# generates and installs the python package
1956# cd {clone_dir}/faiss/build/faiss/python
1957# python setup.py install
1958
1959# make the compiled library (either libfaiss.a or libfaiss.so on Linux) available system-wide, as well as the C++ headers
1960# cd {clone_dir}/faiss
1961# make -C build install
1962"
1963 ))
1964 }
1965 _ => Err(Error::new(
1966 ErrorKind::InvalidInput,
1967 format!("os_type '{}' not supported", os_type.as_str()),
1968 )),
1969 }
1970}
1971
1972pub fn eks_worker_node_ami_scratch(os_type: OsType) -> io::Result<String> {
1973 match os_type {
1974 OsType::Ubuntu2004 | OsType::Ubuntu2204 => Ok("
1975###########################
1976# install EKS worker node AMI (from scratch)
1977# https://github.com/awslabs/amazon-eks-ami/blob/master/scripts/install-worker.sh
1978
1979#######
1980# install packages
1981# https://github.com/awslabs/amazon-eks-ami/blob/master/scripts/install-worker.sh
1982#######
1983while [ 1 ]; do
1984 sudo apt-get update -yq
1985 sudo apt-get upgrade -yq
1986 sudo apt-get install -yq conntrack socat nfs-kernel-server ipvsadm
1987 sudo apt-get clean
1988 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
1989 sleep 2s;
1990done;
1991
1992#######
1993### Stuff required by \"protectKernelDefaults=true\"
1994# https://github.com/awslabs/amazon-eks-ami/blob/master/scripts/install-worker.sh
1995#######
1996cat << EOF | sudo tee -a /etc/sysctl.d/99-amazon.conf
1997vm.overcommit_memory=1
1998kernel.panic=10
1999kernel.panic_on_oops=1
2000EOF
2001
2002#######
2003# set up nvidia-smi check scripts
2004# https://github.com/awslabs/amazon-eks-ami/blob/master/files/bootstrap.sh
2005#######
2006# https://stackoverflow.com/questions/27920806/how-to-avoid-heredoc-expanding-variables
2007cat << 'EOF' > /tmp/check-nvidia-smi.sh
2008#!/usr/bin/env bash
2009
2010if command -v nvidia-smi &> /dev/null; then
2011 echo \"INFO: nvidia-smi found\"
2012
2013 nvidia-smi -q > /tmp/nvidia-smi-check
2014 if [[ \"$?\" == \"0\" ]]; then
2015 sudo nvidia-smi -pm 1 # set persistence mode
2016 sudo nvidia-smi --auto-boost-default=0
2017
2018 GPUNAME=$(nvidia-smi -L | head -n1)
2019 echo \"INFO: GPU name: $GPUNAME\"
2020
2021 # set application clock to maximum
2022 if [[ $GPUNAME == *\"A100\"* ]]; then
2023 nvidia-smi -ac 1215,1410
2024 elif [[ $GPUNAME == *\"V100\"* ]]; then
2025 nvidia-smi -ac 877,1530
2026 elif [[ $GPUNAME == *\"K80\"* ]]; then
2027 nvidia-smi -ac 2505,875
2028 elif [[ $GPUNAME == *\"T4\"* ]]; then
2029 nvidia-smi -ac 5001,1590
2030 elif [[ $GPUNAME == *\"M60\"* ]]; then
2031 nvidia-smi -ac 2505,1177
2032 else
2033 echo \"WARN: unsupported GPU\"
2034 fi
2035 else
2036 echo \"ERROR: nvidia-smi check failed!\"
2037 cat /tmp/nvidia-smi-check
2038 fi
2039else
2040 echo \"INFO: nvidia-smi NOT found\"
2041fi
2042EOF
2043cat /tmp/check-nvidia-smi.sh
2044chmod +x /tmp/check-nvidia-smi.sh
2045sudo mv /tmp/check-nvidia-smi.sh /etc/check-nvidia-smi.sh
2046
2047#######
2048# set up files
2049# https://github.com/awslabs/amazon-eks-ami/blob/master/scripts/install-worker.sh
2050#######
2051sudo mkdir -p /etc/eks
2052sudo chown -R root:root /etc/eks
2053
2054targets=(
2055 get-ecr-uri.sh
2056 eni-max-pods.txt
2057 bootstrap.sh
2058 max-pods-calculator.sh
2059)
2060for target in \"${targets[@]}\"
2061do
2062 while [ 1 ]; do
2063 rm -f /tmp/${target} || true;
2064 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://raw.githubusercontent.com/awslabs/amazon-eks-ami/master/files/${target}\"
2065 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
2066 sleep 2s;
2067 done;
2068 chmod +x /tmp/${target}
2069 sudo mv /tmp/${target} /etc/eks/${target}
2070done
2071
2072sudo chown -R root:root /etc/eks
2073sudo chown -R ubuntu:ubuntu /etc/eks
2074find /etc/eks
2075
2076#######
2077# set up iptables
2078# https://github.com/awslabs/amazon-eks-ami/blob/master/scripts/install-worker.sh
2079#######
2080sudo mkdir -p /etc/eks
2081sudo chown -R root:root /etc/eks
2082
2083while [ 1 ]; do
2084 rm -f /tmp/iptables-restore.service || true;
2085 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://raw.githubusercontent.com/awslabs/amazon-eks-ami/master/files/iptables-restore.service\"
2086 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
2087 sleep 2s;
2088done;
2089chmod +x /tmp/iptables-restore.service
2090sudo mv /tmp/iptables-restore.service /etc/eks/iptables-restore.service
2091
2092sudo chown -R root:root /etc/eks
2093sudo chown -R ubuntu:ubuntu /etc/eks
2094find /etc/eks
2095
2096#######
2097# set up containerd
2098# https://github.com/awslabs/amazon-eks-ami/blob/master/scripts/install-worker.sh
2099#######
2100sudo mkdir -p /etc/eks
2101sudo chown -R root:root /etc/eks
2102sudo mkdir -p /etc/eks/containerd
2103
2104targets=(
2105 containerd-config.toml
2106 kubelet-containerd.service
2107 sandbox-image.service
2108 pull-sandbox-image.sh
2109 pull-image.sh
2110)
2111for target in \"${targets[@]}\"
2112do
2113 while [ 1 ]; do
2114 rm -f /tmp/${target} || true;
2115 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://raw.githubusercontent.com/awslabs/amazon-eks-ami/master/files/${target}\"
2116 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
2117 sleep 2s;
2118 done;
2119 chmod +x /tmp/${target}
2120 sudo mv /tmp/${target} /etc/eks/containerd/${target}
2121done
2122
2123sudo chown -R root:root /etc/eks
2124sudo chown -R ubuntu:ubuntu /etc/eks
2125find /etc/eks
2126
2127sudo mkdir -p /etc/systemd/system/containerd.service.d
2128cat << EOF | sudo tee /etc/systemd/system/containerd.service.d/10-compat-symlink.conf
2129[Service]
2130ExecStartPre=/bin/ln -sf /run/containerd/containerd.sock /run/dockershim.sock
2131EOF
2132
2133cat << EOF | sudo tee -a /etc/modules-load.d/containerd.conf
2134overlay
2135br_netfilter
2136EOF
2137
2138cat << EOF | sudo tee -a /etc/sysctl.d/99-kubernetes-cri.conf
2139net.bridge.bridge-nf-call-ip6tables = 1
2140net.bridge.bridge-nf-call-iptables = 1
2141net.ipv4.ip_forward = 1
2142EOF
2143
2144cat << EOF | sudo tee /etc/systemd/system/containerd.service
2145[Unit]
2146Description=containerd
2147Documentation=https://containerd.io
2148
2149[Service]
2150Type=notify
2151ExecStart=/usr/bin/containerd
2152
2153[Install]
2154WantedBy=multi-user.target
2155EOF
2156
2157sudo systemctl enable containerd
2158sudo systemctl restart containerd
2159sudo ctr version || true
2160
2161#######
2162# set up log-collector for EKS
2163# https://github.com/awslabs/amazon-eks-ami/blob/master/scripts/install-worker.sh
2164#######
2165sudo mkdir -p /etc/eks
2166sudo chown -R root:root /etc/eks
2167sudo mkdir -p /etc/eks/log-collector-script/
2168
2169while [ 1 ]; do
2170 rm -f /tmp/eks-log-collector.sh || true;
2171 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://raw.githubusercontent.com/awslabs/amazon-eks-ami/master/log-collector-script/linux/eks-log-collector.sh\"
2172 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
2173 sleep 2s;
2174done;
2175chmod +x /tmp/eks-log-collector.sh
2176sudo mv /tmp/eks-log-collector.sh /etc/eks/log-collector-script/eks-log-collector.sh
2177
2178sudo chown -R root:root /etc/eks
2179sudo chown -R ubuntu:ubuntu /etc/eks
2180find /etc/eks
2181
2182#######
2183# set up logrotate for kube-proxy
2184# https://github.com/awslabs/amazon-eks-ami/blob/master/scripts/install-worker.sh
2185#######
2186sudo mkdir -p /var/log/journal
2187
2188while [ 1 ]; do
2189 rm -f /tmp/logrotate-kube-proxy || true;
2190 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://raw.githubusercontent.com/awslabs/amazon-eks-ami/master/files/logrotate-kube-proxy\"
2191 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
2192 sleep 2s;
2193done;
2194sudo mv /tmp/logrotate-kube-proxy /etc/logrotate.d/kube-proxy
2195sudo chown root:root /etc/logrotate.d/kube-proxy
2196
2197while [ 1 ]; do
2198 rm -f /tmp/logrotate.conf || true;
2199 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://raw.githubusercontent.com/awslabs/amazon-eks-ami/master/files/logrotate.conf\"
2200 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
2201 sleep 2s;
2202done;
2203sudo mv /tmp/logrotate.conf /etc/logrotate.conf
2204sudo chown root:root /etc/logrotate.conf
2205
2206#######
2207# set up kubernetes
2208# https://github.com/awslabs/amazon-eks-ami/blob/master/scripts/install-worker.sh
2209#######
2210sudo mkdir -p /var/lib/kubernetes
2211sudo mkdir -p /var/lib/kubelet
2212sudo mkdir -p /etc/kubernetes
2213sudo mkdir -p /etc/kubernetes/manifests
2214sudo mkdir -p /etc/kubernetes/kubelet
2215sudo mkdir -p /etc/systemd/system/kubelet.service.d
2216
2217while [ 1 ]; do
2218 rm -f /tmp/kubelet-kubeconfig || true;
2219 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://raw.githubusercontent.com/awslabs/amazon-eks-ami/master/files/kubelet-kubeconfig\"
2220 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
2221 sleep 2s;
2222done;
2223sudo mv /tmp/kubelet-kubeconfig /var/lib/kubelet/kubeconfig
2224sudo chown root:root /var/lib/kubelet/kubeconfig
2225
2226while [ 1 ]; do
2227 rm -f /tmp/kubelet.service || true;
2228 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://raw.githubusercontent.com/awslabs/amazon-eks-ami/master/files/kubelet.service\"
2229 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
2230 sleep 2s;
2231done;
2232sudo mv /tmp/kubelet.service /etc/systemd/system/kubelet.service
2233sudo chown root:root /etc/systemd/system/kubelet.service
2234
2235while [ 1 ]; do
2236 rm -f /tmp/kubelet-config.json || true;
2237 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://raw.githubusercontent.com/awslabs/amazon-eks-ami/master/files/kubelet-config.json\"
2238 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
2239 sleep 2s;
2240done;
2241sudo mv /tmp/kubelet-config.json /etc/kubernetes/kubelet/kubelet-config.json
2242sudo chown root:root /etc/kubernetes/kubelet/kubelet-config.json
2243
2244sudo systemctl daemon-reload
2245sudo systemctl disable kubelet
2246
2247#######
2248# cache images
2249# https://github.com/awslabs/amazon-eks-ami/blob/master/scripts/install-worker.sh
2250#######
2251ISOLATED_REGIONS=${ISOLATED_REGIONS:-us-iso-east-1 us-iso-west-1 us-isob-east-1}
2252EKS_CACHE_CONTAINER_IMAGES=${EKS_CACHE_CONTAINER_IMAGES:-true}
2253BINARY_BUCKET_REGION=${BINARY_BUCKET_REGION:-us-west-2}
2254PAUSE_CONTAINER_VERSION=${PAUSE_CONTAINER_VERSION:-3.5}
2255KUBERNETES_VERSION=${KUBERNETES_VERSION:-1.26}
2256
2257if [[ \"$EKS_CACHE_CONTAINER_IMAGES\" == \"true\" ]] && ! [[ ${ISOLATED_REGIONS} =~ $BINARY_BUCKET_REGION ]]; then
2258 AWS_DOMAIN=$(imds 'latest/meta-data/services/domain')
2259 ECR_URI=$(/etc/eks/get-ecr-uri.sh \"${BINARY_BUCKET_REGION}\" \"${AWS_DOMAIN}\")
2260
2261 PAUSE_CONTAINER=\"${ECR_URI}/eks/pause:${PAUSE_CONTAINER_VERSION}\"
2262 echo \"PAUSE_CONTAINER: ${PAUSE_CONTAINER}\"
2263
2264 cat /etc/eks/containerd/containerd-config.toml | sed s,SANDBOX_IMAGE,$PAUSE_CONTAINER,g | sudo tee /etc/eks/containerd/containerd-cached-pause-config.toml
2265
2266 sudo mkdir -p /etc/containerd
2267 sudo chown -R root:root /etc/containerd
2268 sudo cp -v /etc/eks/containerd/containerd-cached-pause-config.toml /etc/containerd/config.toml
2269 sudo cp -v /etc/eks/containerd/sandbox-image.service /etc/systemd/system/sandbox-image.service
2270 sudo chown root:root /etc/systemd/system/sandbox-image.service
2271
2272 sudo systemctl daemon-reload
2273 sudo systemctl restart containerd
2274 sudo systemctl enable containerd sandbox-image
2275
2276 # e.g., 1.26
2277 K8S_MINOR_VERSION=$(echo \"${KUBERNETES_VERSION}\" | cut -d'.' -f1-2)
2278 echo \"K8S_MINOR_VERSION: ${K8S_MINOR_VERSION}\"
2279
2280 #### Cache kube-proxy images starting with the addon default version and the latest version
2281 KUBE_PROXY_ADDON_VERSIONS=$(aws eks describe-addon-versions --addon-name kube-proxy --kubernetes-version=${K8S_MINOR_VERSION})
2282 echo \"KUBE_PROXY_ADDON_VERSIONS: ${KUBE_PROXY_ADDON_VERSIONS}\"
2283
2284 KUBE_PROXY_IMGS=()
2285 if [[ $(jq '.addons | length' <<< $KUBE_PROXY_ADDON_VERSIONS) -gt 0 ]]; then
2286 DEFAULT_KUBE_PROXY_FULL_VERSION=$(echo \"${KUBE_PROXY_ADDON_VERSIONS}\" | jq -r '.addons[] .addonVersions[] | select(.compatibilities[] .defaultVersion==true).addonVersion')
2287 DEFAULT_KUBE_PROXY_VERSION=$(echo \"${DEFAULT_KUBE_PROXY_FULL_VERSION}\" | cut -d\"-\" -f1)
2288 DEFAULT_KUBE_PROXY_PLATFORM_VERSION=$(echo \"${DEFAULT_KUBE_PROXY_FULL_VERSION}\" | cut -d\"-\" -f2)
2289
2290 LATEST_KUBE_PROXY_FULL_VERSION=$(echo \"${KUBE_PROXY_ADDON_VERSIONS}\" | jq -r '.addons[] .addonVersions[] .addonVersion' | sort -V | tail -n1)
2291 LATEST_KUBE_PROXY_VERSION=$(echo \"${LATEST_KUBE_PROXY_FULL_VERSION}\" | cut -d\"-\" -f1)
2292 LATEST_KUBE_PROXY_PLATFORM_VERSION=$(echo \"${LATEST_KUBE_PROXY_FULL_VERSION}\" | cut -d\"-\" -f2)
2293
2294 KUBE_PROXY_IMGS=(
2295 ## Default kube-proxy images
2296 \"${ECR_URI}/eks/kube-proxy:${DEFAULT_KUBE_PROXY_VERSION}-${DEFAULT_KUBE_PROXY_PLATFORM_VERSION}\"
2297 \"${ECR_URI}/eks/kube-proxy:${DEFAULT_KUBE_PROXY_VERSION}-minimal-${DEFAULT_KUBE_PROXY_PLATFORM_VERSION}\"
2298
2299 ## Latest kube-proxy images
2300 \"${ECR_URI}/eks/kube-proxy:${LATEST_KUBE_PROXY_VERSION}-${LATEST_KUBE_PROXY_PLATFORM_VERSION}\"
2301 \"${ECR_URI}/eks/kube-proxy:${LATEST_KUBE_PROXY_VERSION}-minimal-${LATEST_KUBE_PROXY_PLATFORM_VERSION}\"
2302 )
2303 fi
2304 echo \"KUBE_PROXY_IMGS: ${KUBE_PROXY_IMGS}\"
2305
2306 #### Cache VPC CNI images starting with the addon default version and the latest version
2307 VPC_CNI_ADDON_VERSIONS=$(aws eks describe-addon-versions --addon-name vpc-cni --kubernetes-version=${K8S_MINOR_VERSION})
2308 echo \"VPC_CNI_ADDON_VERSIONS: ${VPC_CNI_ADDON_VERSIONS}\"
2309
2310 VPC_CNI_IMGS=()
2311 if [[ $(jq '.addons | length' <<< $VPC_CNI_ADDON_VERSIONS) -gt 0 ]]; then
2312 DEFAULT_VPC_CNI_VERSION=$(echo \"${VPC_CNI_ADDON_VERSIONS}\" | jq -r '.addons[] .addonVersions[] | select(.compatibilities[] .defaultVersion==true).addonVersion')
2313 LATEST_VPC_CNI_VERSION=$(echo \"${VPC_CNI_ADDON_VERSIONS}\" | jq -r '.addons[] .addonVersions[] .addonVersion' | sort -V | tail -n1)
2314 CNI_IMG=\"${ECR_URI}/amazon-k8s-cni\"
2315 CNI_INIT_IMG=\"${CNI_IMG}-init\"
2316
2317 VPC_CNI_IMGS=(
2318 ## Default VPC CNI Images
2319 \"${CNI_IMG}:${DEFAULT_VPC_CNI_VERSION}\"
2320 \"${CNI_INIT_IMG}:${DEFAULT_VPC_CNI_VERSION}\"
2321
2322 ## Latest VPC CNI Images
2323 \"${CNI_IMG}:${LATEST_VPC_CNI_VERSION}\"
2324 \"${CNI_INIT_IMG}:${LATEST_VPC_CNI_VERSION}\"
2325 )
2326 fi
2327 echo \"VPC_CNI_IMGS: ${VPC_CNI_IMGS}\"
2328
2329 CACHE_IMGS=(
2330 \"${PAUSE_CONTAINER}\"
2331 ${KUBE_PROXY_IMGS[@]+\"${KUBE_PROXY_IMGS[@]}\"}
2332 ${VPC_CNI_IMGS[@]+\"${VPC_CNI_IMGS[@]}\"}
2333 )
2334 echo \"CACHE_IMGS: ${CACHE_IMGS}\"
2335
2336 PULLED_IMGS=()
2337 for img in \"${CACHE_IMGS[@]}\"; do
2338 ## only kube-proxy-minimal is vended for K8s 1.24+
2339 if [[ \"${img}\" == *\"kube-proxy:\"* ]] && [[ \"${img}\" != *\"-minimal-\"* ]] && vercmp \"${K8S_MINOR_VERSION}\" gteq \"1.24\"; then
2340 continue
2341 fi
2342
2343 ## Since eksbuild.x version may not match the image tag, we need to decrement the eksbuild version until we find the latest image tag within the app semver
2344 eksbuild_version=\"1\"
2345 if [[ ${img} == *'eksbuild.'* ]]; then
2346 eksbuild_version=$(echo \"${img}\" | grep -o 'eksbuild\\.[0-9]\\+' | cut -d'.' -f2)
2347 fi
2348
2349 ## iterate through decrementing the build version each time
2350 for build_version in $(seq \"${eksbuild_version}\" -1 1); do
2351 img=$(echo \"${img}\" | sed -E \"s/eksbuild.[0-9]+/eksbuild.${build_version}/\")
2352 echo \"ctr pulling/fetching an image ${img}\"
2353 if /etc/eks/containerd/pull-image.sh \"${img}\"; then
2354 PULLED_IMGS+=(\"${img}\")
2355 break
2356 elif [[ \"${build_version}\" -eq 1 ]]; then
2357 exit 1
2358 fi
2359 done
2360 done
2361 echo \"PULLED_IMGS: ${PULLED_IMGS}\"
2362
2363 #### Tag the pulled down image for all other regions in the partition
2364 for region in $(aws ec2 describe-regions --all-regions | jq -r '.Regions[] .RegionName'); do
2365 for img in \"${PULLED_IMGS[@]}\"; do
2366 regional_img=\"${img/$BINARY_BUCKET_REGION/$region}\"
2367 echo \"tagging a pulled image ${regional_img}\"
2368 sudo ctr -n k8s.io image tag \"${img}\" \"${regional_img}\" || :
2369
2370 ## Tag ECR fips endpoint for supported regions
2371 if [[ \"${region}\" =~ (us-east-1|us-east-2|us-west-1|us-west-2|us-gov-east-1|us-gov-east-2) ]]; then
2372 regional_fips_img=\"${regional_img/.ecr./.ecr-fips.}\"
2373 sudo ctr -n k8s.io image tag \"${img}\" \"${regional_fips_img}\" || :
2374 sudo ctr -n k8s.io image tag \"${img}\" \"${regional_fips_img/-eksbuild.1/}\" || :
2375 fi
2376
2377 ## Cache the non-addon VPC CNI images since \"v*.*.*-eksbuild.1\" is equivalent to leaving off the eksbuild suffix
2378 if [[ \"${img}\" == *\"-cni\"*\"-eksbuild.1\" ]]; then
2379 sudo ctr -n k8s.io image tag \"${img}\" \"${regional_img/-eksbuild.1/}\" || :
2380 fi
2381 done
2382 done
2383fi
2384
2385#######
2386# write release file
2387# https://github.com/awslabs/amazon-eks-ami/blob/master/scripts/install-worker.sh
2388# 'uname -m' to decide x86_64/aarch64
2389#######
2390BASE_AMI_ID=$(imds /latest/meta-data/ami-id)
2391sudo rm -f /tmp/release-full
2392cat << EOF > /tmp/release-full
2393BASE_AMI_ID=$BASE_AMI_ID
2394BUILD_TIME=$(date)
2395BUILD_KERNEL=$(uname -r)
2396ARCH=$(uname -m)
2397
2398OS_RELEASE_ID=$(. /etc/os-release;echo $ID)
2399OS_RELEASE_DISTRIBUTION=$(. /etc/os-release;echo $ID$VERSION_ID)
2400
2401RUNC_VERSION=\"$(runc --version | head -1 | tr -d '\\n')\"
2402CONTAINERD_VERSION=\"$(containerd --version)\"
2403CTR_VERSION=\"$(ctr --version)\"
2404
2405KUBELET_VERSION=\"$(kubelet --version)\"
2406EOF
2407cat /tmp/release-full
2408
2409sudo cp -v /tmp/release-full /etc/release-full
2410sudo chmod 0444 /etc/release-full
2411"
2412 .to_string()),
2413 _ => Err(Error::new(
2414 ErrorKind::InvalidInput,
2415 format!("os_type '{}' not supported", os_type.as_str()),
2416 )),
2417 }
2418}
2419
2420pub fn eks_worker_node_ami_reuse(os_type: OsType) -> io::Result<String> {
2421 match os_type {
2422 OsType::Ubuntu2004 | OsType::Ubuntu2204 => Ok("
2423###########################
2424# install EKS worker node AMI (minimum)
2425# to build on top of the existing ubuntu AMI
2426# https://github.com/awslabs/amazon-eks-ami/blob/master/scripts/install-worker.sh
2427
2428#######
2429# set up nvidia-smi check scripts
2430# https://github.com/awslabs/amazon-eks-ami/blob/master/files/bootstrap.sh
2431#######
2432# https://stackoverflow.com/questions/27920806/how-to-avoid-heredoc-expanding-variables
2433cat << 'EOF' > /tmp/check-nvidia-smi.sh
2434#!/usr/bin/env bash
2435
2436if command -v nvidia-smi &> /dev/null; then
2437 echo \"INFO: nvidia-smi found\"
2438
2439 nvidia-smi -q > /tmp/nvidia-smi-check
2440 if [[ \"$?\" == \"0\" ]]; then
2441 sudo nvidia-smi -pm 1 # set persistence mode
2442 sudo nvidia-smi --auto-boost-default=0
2443
2444 GPUNAME=$(nvidia-smi -L | head -n1)
2445 echo \"INFO: GPU name: $GPUNAME\"
2446
2447 # set application clock to maximum
2448 if [[ $GPUNAME == *\"A100\"* ]]; then
2449 nvidia-smi -ac 1215,1410
2450 elif [[ $GPUNAME == *\"V100\"* ]]; then
2451 nvidia-smi -ac 877,1530
2452 elif [[ $GPUNAME == *\"K80\"* ]]; then
2453 nvidia-smi -ac 2505,875
2454 elif [[ $GPUNAME == *\"T4\"* ]]; then
2455 nvidia-smi -ac 5001,1590
2456 elif [[ $GPUNAME == *\"M60\"* ]]; then
2457 nvidia-smi -ac 2505,1177
2458 else
2459 echo \"WARN: unsupported GPU\"
2460 fi
2461 else
2462 echo \"ERROR: nvidia-smi check failed!\"
2463 cat /tmp/nvidia-smi-check
2464 fi
2465else
2466 echo \"INFO: nvidia-smi NOT found\"
2467fi
2468EOF
2469cat /tmp/check-nvidia-smi.sh
2470chmod +x /tmp/check-nvidia-smi.sh
2471sudo mv /tmp/check-nvidia-smi.sh /etc/check-nvidia-smi.sh
2472
2473#######
2474# set up files
2475# https://github.com/awslabs/amazon-eks-ami/blob/master/scripts/install-worker.sh
2476#######
2477sudo mkdir -p /etc/eks
2478sudo chown -R root:root /etc/eks
2479sudo mkdir -p /etc/eks/containerd
2480
2481# https://github.com/awslabs/amazon-eks-ami/commit/7c45ddef58bbb50c869095eeb2185e41a745db6f
2482targets=(
2483 containerd-config.toml
2484 eni-max-pods.txt
2485 get-ecr-uri.sh
2486 pull-image.sh
2487 pull-sandbox-image.sh
2488 sandbox-image.service
2489)
2490for target in \"${targets[@]}\"
2491do
2492 while [ 1 ]; do
2493 rm -f /tmp/${target} || true;
2494 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://raw.githubusercontent.com/awslabs/amazon-eks-ami/master/files/${target}\"
2495 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
2496 sleep 2s;
2497 done;
2498 chmod +x /tmp/${target}
2499 sudo cp -v /tmp/${target} /etc/eks/containerd/${target}
2500 sudo mv /tmp/${target} /etc/eks/${target}
2501done
2502
2503sudo chown -R root:root /etc/eks
2504sudo chown -R ubuntu:ubuntu /etc/eks
2505find /etc/eks
2506
2507sudo ctr version || true
2508
2509#######
2510# set up log-collector for EKS
2511# https://github.com/awslabs/amazon-eks-ami/blob/master/scripts/install-worker.sh
2512#######
2513sudo mkdir -p /etc/eks
2514sudo chown -R root:root /etc/eks
2515sudo mkdir -p /etc/eks/log-collector-script/
2516
2517while [ 1 ]; do
2518 rm -f /tmp/eks-log-collector.sh || true;
2519 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://raw.githubusercontent.com/awslabs/amazon-eks-ami/master/log-collector-script/linux/eks-log-collector.sh\"
2520 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
2521 sleep 2s;
2522done;
2523chmod +x /tmp/eks-log-collector.sh
2524sudo mv /tmp/eks-log-collector.sh /etc/eks/log-collector-script/eks-log-collector.sh
2525
2526sudo chown -R root:root /etc/eks
2527sudo chown -R ubuntu:ubuntu /etc/eks
2528find /etc/eks
2529
2530#######
2531# set up logrotate for kube-proxy
2532# https://github.com/awslabs/amazon-eks-ami/blob/master/scripts/install-worker.sh
2533#######
2534sudo mkdir -p /var/log/journal
2535
2536while [ 1 ]; do
2537 rm -f /tmp/logrotate-kube-proxy || true;
2538 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://raw.githubusercontent.com/awslabs/amazon-eks-ami/master/files/logrotate-kube-proxy\"
2539 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
2540 sleep 2s;
2541done;
2542sudo mv /tmp/logrotate-kube-proxy /etc/logrotate.d/kube-proxy
2543sudo chown root:root /etc/logrotate.d/kube-proxy
2544
2545while [ 1 ]; do
2546 rm -f /tmp/logrotate.conf || true;
2547 wget --quiet --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries=70 --directory-prefix=/tmp/ --continue \"https://raw.githubusercontent.com/awslabs/amazon-eks-ami/master/files/logrotate.conf\"
2548 if [ $? = 0 ]; then break; fi; # check return value, break if successful (0)
2549 sleep 2s;
2550done;
2551sudo mv /tmp/logrotate.conf /etc/logrotate.conf
2552sudo chown root:root /etc/logrotate.conf
2553
2554#######
2555# cache images
2556# https://github.com/awslabs/amazon-eks-ami/blob/master/scripts/install-worker.sh
2557#######
2558ISOLATED_REGIONS=${ISOLATED_REGIONS:-us-iso-east-1 us-iso-west-1 us-isob-east-1}
2559EKS_CACHE_CONTAINER_IMAGES=${EKS_CACHE_CONTAINER_IMAGES:-true}
2560BINARY_BUCKET_REGION=${BINARY_BUCKET_REGION:-us-west-2}
2561PAUSE_CONTAINER_VERSION=${PAUSE_CONTAINER_VERSION:-3.5}
2562KUBERNETES_VERSION=${KUBERNETES_VERSION:-1.26}
2563
2564if [[ \"$EKS_CACHE_CONTAINER_IMAGES\" == \"true\" ]] && ! [[ ${ISOLATED_REGIONS} =~ $BINARY_BUCKET_REGION ]]; then
2565 AWS_DOMAIN=$(imds 'latest/meta-data/services/domain')
2566 ECR_URI=$(/etc/eks/get-ecr-uri.sh \"${BINARY_BUCKET_REGION}\" \"${AWS_DOMAIN}\")
2567
2568 PAUSE_CONTAINER=\"${ECR_URI}/eks/pause:${PAUSE_CONTAINER_VERSION}\"
2569 echo \"PAUSE_CONTAINER: ${PAUSE_CONTAINER}\"
2570
2571 cat /etc/eks/containerd/containerd-config.toml | sed s,SANDBOX_IMAGE,$PAUSE_CONTAINER,g | sudo tee /etc/eks/containerd/containerd-cached-pause-config.toml
2572
2573 sudo mkdir -p /etc/containerd
2574 sudo chown -R root:root /etc/containerd
2575 sudo cp -v /etc/eks/containerd/containerd-cached-pause-config.toml /etc/containerd/config.toml
2576 sudo cp -v /etc/eks/containerd/sandbox-image.service /etc/systemd/system/sandbox-image.service
2577 sudo chown root:root /etc/systemd/system/sandbox-image.service
2578
2579 sudo systemctl daemon-reload
2580 sudo systemctl restart containerd
2581 sudo systemctl enable containerd sandbox-image
2582
2583 # e.g., 1.26
2584 K8S_MINOR_VERSION=$(echo \"${KUBERNETES_VERSION}\" | cut -d'.' -f1-2)
2585 echo \"K8S_MINOR_VERSION: ${K8S_MINOR_VERSION}\"
2586
2587 #### Cache kube-proxy images starting with the addon default version and the latest version
2588 KUBE_PROXY_ADDON_VERSIONS=$(aws eks describe-addon-versions --addon-name kube-proxy --kubernetes-version=${K8S_MINOR_VERSION})
2589 echo \"KUBE_PROXY_ADDON_VERSIONS: ${KUBE_PROXY_ADDON_VERSIONS}\"
2590
2591 KUBE_PROXY_IMGS=()
2592 if [[ $(jq '.addons | length' <<< $KUBE_PROXY_ADDON_VERSIONS) -gt 0 ]]; then
2593 DEFAULT_KUBE_PROXY_FULL_VERSION=$(echo \"${KUBE_PROXY_ADDON_VERSIONS}\" | jq -r '.addons[] .addonVersions[] | select(.compatibilities[] .defaultVersion==true).addonVersion')
2594 DEFAULT_KUBE_PROXY_VERSION=$(echo \"${DEFAULT_KUBE_PROXY_FULL_VERSION}\" | cut -d\"-\" -f1)
2595 DEFAULT_KUBE_PROXY_PLATFORM_VERSION=$(echo \"${DEFAULT_KUBE_PROXY_FULL_VERSION}\" | cut -d\"-\" -f2)
2596
2597 LATEST_KUBE_PROXY_FULL_VERSION=$(echo \"${KUBE_PROXY_ADDON_VERSIONS}\" | jq -r '.addons[] .addonVersions[] .addonVersion' | sort -V | tail -n1)
2598 LATEST_KUBE_PROXY_VERSION=$(echo \"${LATEST_KUBE_PROXY_FULL_VERSION}\" | cut -d\"-\" -f1)
2599 LATEST_KUBE_PROXY_PLATFORM_VERSION=$(echo \"${LATEST_KUBE_PROXY_FULL_VERSION}\" | cut -d\"-\" -f2)
2600
2601 KUBE_PROXY_IMGS=(
2602 ## Default kube-proxy images
2603 \"${ECR_URI}/eks/kube-proxy:${DEFAULT_KUBE_PROXY_VERSION}-${DEFAULT_KUBE_PROXY_PLATFORM_VERSION}\"
2604 \"${ECR_URI}/eks/kube-proxy:${DEFAULT_KUBE_PROXY_VERSION}-minimal-${DEFAULT_KUBE_PROXY_PLATFORM_VERSION}\"
2605
2606 ## Latest kube-proxy images
2607 \"${ECR_URI}/eks/kube-proxy:${LATEST_KUBE_PROXY_VERSION}-${LATEST_KUBE_PROXY_PLATFORM_VERSION}\"
2608 \"${ECR_URI}/eks/kube-proxy:${LATEST_KUBE_PROXY_VERSION}-minimal-${LATEST_KUBE_PROXY_PLATFORM_VERSION}\"
2609 )
2610 fi
2611 echo \"KUBE_PROXY_IMGS: ${KUBE_PROXY_IMGS}\"
2612
2613 #### Cache VPC CNI images starting with the addon default version and the latest version
2614 VPC_CNI_ADDON_VERSIONS=$(aws eks describe-addon-versions --addon-name vpc-cni --kubernetes-version=${K8S_MINOR_VERSION})
2615 echo \"VPC_CNI_ADDON_VERSIONS: ${VPC_CNI_ADDON_VERSIONS}\"
2616
2617 VPC_CNI_IMGS=()
2618 if [[ $(jq '.addons | length' <<< $VPC_CNI_ADDON_VERSIONS) -gt 0 ]]; then
2619 DEFAULT_VPC_CNI_VERSION=$(echo \"${VPC_CNI_ADDON_VERSIONS}\" | jq -r '.addons[] .addonVersions[] | select(.compatibilities[] .defaultVersion==true).addonVersion')
2620 LATEST_VPC_CNI_VERSION=$(echo \"${VPC_CNI_ADDON_VERSIONS}\" | jq -r '.addons[] .addonVersions[] .addonVersion' | sort -V | tail -n1)
2621 CNI_IMG=\"${ECR_URI}/amazon-k8s-cni\"
2622 CNI_INIT_IMG=\"${CNI_IMG}-init\"
2623
2624 VPC_CNI_IMGS=(
2625 ## Default VPC CNI Images
2626 \"${CNI_IMG}:${DEFAULT_VPC_CNI_VERSION}\"
2627 \"${CNI_INIT_IMG}:${DEFAULT_VPC_CNI_VERSION}\"
2628
2629 ## Latest VPC CNI Images
2630 \"${CNI_IMG}:${LATEST_VPC_CNI_VERSION}\"
2631 \"${CNI_INIT_IMG}:${LATEST_VPC_CNI_VERSION}\"
2632 )
2633 fi
2634 echo \"VPC_CNI_IMGS: ${VPC_CNI_IMGS}\"
2635
2636 CACHE_IMGS=(
2637 \"${PAUSE_CONTAINER}\"
2638 ${KUBE_PROXY_IMGS[@]+\"${KUBE_PROXY_IMGS[@]}\"}
2639 ${VPC_CNI_IMGS[@]+\"${VPC_CNI_IMGS[@]}\"}
2640 )
2641 echo \"CACHE_IMGS: ${CACHE_IMGS}\"
2642
2643 PULLED_IMGS=()
2644 for img in \"${CACHE_IMGS[@]}\"; do
2645 ## only kube-proxy-minimal is vended for K8s 1.24+
2646 if [[ \"${img}\" == *\"kube-proxy:\"* ]] && [[ \"${img}\" != *\"-minimal-\"* ]] && vercmp \"${K8S_MINOR_VERSION}\" gteq \"1.24\"; then
2647 continue
2648 fi
2649
2650 ## Since eksbuild.x version may not match the image tag, we need to decrement the eksbuild version until we find the latest image tag within the app semver
2651 eksbuild_version=\"1\"
2652 if [[ ${img} == *'eksbuild.'* ]]; then
2653 eksbuild_version=$(echo \"${img}\" | grep -o 'eksbuild\\.[0-9]\\+' | cut -d'.' -f2)
2654 fi
2655
2656 ## iterate through decrementing the build version each time
2657 for build_version in $(seq \"${eksbuild_version}\" -1 1); do
2658 img=$(echo \"${img}\" | sed -E \"s/eksbuild.[0-9]+/eksbuild.${build_version}/\")
2659 echo \"ctr pulling/fetching an image ${img}\"
2660 if /etc/eks/containerd/pull-image.sh \"${img}\"; then
2661 PULLED_IMGS+=(\"${img}\")
2662 break
2663 elif [[ \"${build_version}\" -eq 1 ]]; then
2664 exit 1
2665 fi
2666 done
2667 done
2668 echo \"PULLED_IMGS: ${PULLED_IMGS}\"
2669
2670 #### Tag the pulled down image for all other regions in the partition
2671 for region in $(aws ec2 describe-regions --all-regions | jq -r '.Regions[] .RegionName'); do
2672 for img in \"${PULLED_IMGS[@]}\"; do
2673 regional_img=\"${img/$BINARY_BUCKET_REGION/$region}\"
2674 echo \"tagging a pulled image ${regional_img}\"
2675 sudo ctr -n k8s.io image tag \"${img}\" \"${regional_img}\" || :
2676
2677 ## Tag ECR fips endpoint for supported regions
2678 if [[ \"${region}\" =~ (us-east-1|us-east-2|us-west-1|us-west-2|us-gov-east-1|us-gov-east-2) ]]; then
2679 regional_fips_img=\"${regional_img/.ecr./.ecr-fips.}\"
2680 sudo ctr -n k8s.io image tag \"${img}\" \"${regional_fips_img}\" || :
2681 sudo ctr -n k8s.io image tag \"${img}\" \"${regional_fips_img/-eksbuild.1/}\" || :
2682 fi
2683
2684 ## Cache the non-addon VPC CNI images since \"v*.*.*-eksbuild.1\" is equivalent to leaving off the eksbuild suffix
2685 if [[ \"${img}\" == *\"-cni\"*\"-eksbuild.1\" ]]; then
2686 sudo ctr -n k8s.io image tag \"${img}\" \"${regional_img/-eksbuild.1/}\" || :
2687 fi
2688 done
2689 done
2690fi
2691
2692#######
2693# write release file
2694# https://github.com/awslabs/amazon-eks-ami/blob/master/scripts/install-worker.sh
2695# 'uname -m' to decide x86_64/aarch64
2696#######
2697BASE_AMI_ID=$(imds /latest/meta-data/ami-id)
2698sudo rm -f /tmp/release-full
2699cat << EOF > /tmp/release-full
2700BASE_AMI_ID=$BASE_AMI_ID
2701BUILD_TIME=$(date)
2702BUILD_KERNEL=$(uname -r)
2703ARCH=$(uname -m)
2704
2705OS_RELEASE_ID=$(. /etc/os-release;echo $ID)
2706OS_RELEASE_DISTRIBUTION=$(. /etc/os-release;echo $ID$VERSION_ID)
2707
2708RUNC_VERSION=\"$(runc --version | head -1 | tr -d '\\n')\"
2709CONTAINERD_VERSION=\"$(containerd --version)\"
2710CTR_VERSION=\"$(ctr --version)\"
2711
2712KUBELET_VERSION=\"$(kubelet --version)\"
2713EOF
2714cat /tmp/release-full
2715
2716sudo cp -v /tmp/release-full /etc/release-full
2717sudo chmod 0444 /etc/release-full
2718"
2719 .to_string()),
2720 _ => Err(Error::new(
2721 ErrorKind::InvalidInput,
2722 format!("os_type '{}' not supported", os_type.as_str()),
2723 )),
2724 }
2725}
2726
2727pub fn aws_key(
2728 os_type: OsType,
2729 region: &str,
2730 aws_secret_key_id: &str,
2731 aws_secret_access_key: &str,
2732) -> io::Result<String> {
2733 match os_type {
2734 OsType::Ubuntu2004 | OsType::Ubuntu2204 => Ok(format!(
2735 "
2736###########################
2737# writing AWS access key
2738
2739# NOTE/SECURITY: this must be deleted when building AMI
2740mkdir -p /home/ubuntu/.aws || true
2741rm -f /home/ubuntu/.aws/config || true
2742set +x
2743cat << EOF > /home/ubuntu/.aws/config
2744[default]
2745region = {region}
2746EOF
2747
2748rm -f /home/ubuntu/.aws/credentials || true
2749set +x
2750cat << EOF > /home/ubuntu/.aws/credentials
2751[default]
2752aws_access_key_id = {aws_secret_key_id}
2753aws_secret_access_key = {aws_secret_access_key}
2754EOF
2755
2756set -x
2757aws sts get-caller-identity
2758",
2759 )),
2760 _ => Err(Error::new(
2761 ErrorKind::InvalidInput,
2762 format!("os_type '{}' not supported", os_type.as_str()),
2763 )),
2764 }
2765}
2766
2767pub fn ami_info(os_type: OsType) -> io::Result<String> {
2768 match os_type {
2769 OsType::Ubuntu2004 | OsType::Ubuntu2204 => Ok("
2770###########################
2771# print/write AMI info
2772# 'uname -m' to decide x86_64/aarch64
2773
2774# sudo find /etc/systemd/system/
2775sudo systemctl daemon-reload
2776sudo systemctl list-units --type=service --no-pager
2777df -h
2778
2779BASE_AMI_ID=$(imds /latest/meta-data/ami-id)
2780sudo rm -f /tmp/release
2781cat << EOF > /tmp/release
2782BASE_AMI_ID=$BASE_AMI_ID
2783BUILD_TIME=$(date)
2784BUILD_KERNEL=$(uname -r)
2785ARCH=$(uname -m)
2786EOF
2787cat /tmp/release
2788
2789sudo cp -v /tmp/release /etc/release
2790sudo chmod 0444 /etc/release
2791"
2792 .to_string()),
2793 _ => Err(Error::new(
2794 ErrorKind::InvalidInput,
2795 format!("os_type '{}' not supported", os_type.as_str()),
2796 )),
2797 }
2798}
2799
2800pub fn cluster_info(s3_bucket: &str, id: &str, data_directory_mounted: bool) -> String {
2801 if data_directory_mounted {
2802 format!(
2803 "
2804###########################
2805# write cluster information, assume /data is mounted
2806
2807echo -n \"{s3_bucket}\" > /data/current_s3_bucket
2808echo -n \"{id}\" > /data/current_id
2809"
2810 )
2811 } else {
2812 format!(
2813 "
2814###########################
2815# write cluster information, assume /data is not mounted
2816
2817echo -n \"{s3_bucket}\" > /tmp/current_s3_bucket
2818echo -n \"{id}\" > /tmp/current_id
2819"
2820 )
2821 }
2822}
2823
2824pub fn cleanup_image_packages(os_type: OsType) -> io::Result<String> {
2825 match os_type {
2826 OsType::Ubuntu2004 | OsType::Ubuntu2204 => Ok("
2827###########################
2828# clean up packages
2829
2830sudo apt clean
2831sudo apt-get clean
2832"
2833 .to_string()),
2834 _ => Err(Error::new(
2835 ErrorKind::InvalidInput,
2836 format!("os_type '{}' not supported", os_type.as_str()),
2837 )),
2838 }
2839}
2840
2841pub fn cleanup_image_tmp_dir(os_type: OsType) -> io::Result<String> {
2842 match os_type {
2843 OsType::Ubuntu2004 | OsType::Ubuntu2204 => Ok("
2844###########################
2845# clean up /tmp directory
2846
2847sudo rm -rf /tmp/*
2848"
2849 .to_string()),
2850 _ => Err(Error::new(
2851 ErrorKind::InvalidInput,
2852 format!("os_type '{}' not supported", os_type.as_str()),
2853 )),
2854 }
2855}
2856
2857pub fn cleanup_image_ssh_keys(os_type: OsType) -> io::Result<String> {
2858 match os_type {
2859 OsType::Ubuntu2004 | OsType::Ubuntu2204 => Ok("
2860###########################
2861# WARN
2862# clean up image (useful/required for AMI builds)
2863# https://github.com/awslabs/amazon-eks-ami/blob/master/scripts/cleanup.sh
2864# https://github.com/awslabs/amazon-eks-ami/blob/master/scripts/validate.sh
2865
2866# sleep enough time for poller
2867# to grab the successful init completion
2868sleep 120
2869
2870sudo rm -rf \\
2871/etc/ssh/ssh_host* \\
2872/home/ubuntu/.ssh/authorized_keys \\
2873/root/.ssh/authorized_keys
2874"
2875 .to_string()),
2876 _ => Err(Error::new(
2877 ErrorKind::InvalidInput,
2878 format!("os_type '{}' not supported", os_type.as_str()),
2879 )),
2880 }
2881}
2882
2883pub fn cleanup_image_aws_credentials(os_type: OsType) -> io::Result<String> {
2884 match os_type {
2885 OsType::Ubuntu2004 | OsType::Ubuntu2204 => Ok("
2886###########################
2887# WARN
2888# clean up AWS credentials
2889# https://github.com/awslabs/amazon-eks-ami/blob/master/scripts/cleanup.sh
2890# https://github.com/awslabs/amazon-eks-ami/blob/master/scripts/validate.sh
2891
2892sudo rm -rf /home/ubuntu/.aws
2893"
2894 .to_string()),
2895
2896 OsType::Al2023 => Ok("
2897###########################
2898# WARN
2899# clean up AWS credentials
2900# https://github.com/awslabs/amazon-eks-ami/blob/master/scripts/cleanup.sh
2901# https://github.com/awslabs/amazon-eks-ami/blob/master/scripts/validate.sh
2902
2903sudo rm -rf /home/ec2-user/.aws
2904"
2905 .to_string()),
2906
2907 _ => Err(Error::new(
2908 ErrorKind::InvalidInput,
2909 format!("os_type '{}' not supported", os_type.as_str()),
2910 )),
2911 }
2912}