mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-01-13 22:30:37 +08:00
Merge remote-tracking branch 'LCTT/master'
This commit is contained in:
commit
d365bad167
@ -1,22 +1,24 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11793-1.html)
|
||||
[#]: subject: (Sync files across multiple devices with Syncthing)
|
||||
[#]: via: (https://opensource.com/article/20/1/sync-files-syncthing)
|
||||
[#]: author: (Kevin Sonney https://opensource.com/users/ksonney)
|
||||
|
||||
使用 Syncthing 在多个设备间同步文件
|
||||
======
|
||||
2020 年,在我们的 20 个使用开源提升生产力的系列文章中,首先了解如何使用 Syncthing 同步文件。
|
||||
![Files in a folder][1]
|
||||
|
||||
> 2020 年,在我们的 20 个使用开源提升生产力的系列文章中,首先了解如何使用 Syncthing 同步文件。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202001/18/123416rebvs7sjwm6c889y.jpg)
|
||||
|
||||
去年,我在 19 天里给你介绍了 19 个新(对你而言)的生产力工具。今年,我换了一种方式:使用你在使用或者还没使用的工具,构建一个使你可以在新一年更加高效的环境。
|
||||
|
||||
### 使用 Synthing 同步文件
|
||||
|
||||
置新机器很麻烦。我们都有在机器之间复制的“标准设置”。多年来,我使用了很多方法来使它们在计算机之间同步。在过去(这会告诉你我年纪有多大了),曾经是软盘、然后是 Zip 磁盘、U 盘、SCP、Rsync、Dropbox、ownCloud,你想到的都试过。但这些似乎对我都不够好。
|
||||
设置新机器很麻烦。我们都有在机器之间复制的“标准设置”。多年来,我使用了很多方法来使它们在计算机之间同步。在过去(这会告诉你我年纪有多大了),曾经是软盘、然后是 Zip 磁盘、U 盘、SCP、Rsync、Dropbox、ownCloud,你想到的都试过。但这些似乎对我都不够好。
|
||||
|
||||
然后我偶然发现了 [Syncthing][2]。
|
||||
|
||||
@ -28,19 +30,19 @@ Syncthing 可在 Linux、MacOS、Windows 和多种 BSD 中使用。还有一个
|
||||
|
||||
![Installing Syncthing on Ubuntu][4]
|
||||
|
||||
首次启动 Syncthing 时,它将启动 Web 浏览器以配置守护程序。第一台计算机上没有太多要做,但是这是一个很好的机会来介绍一下用户界面 (UI)。最重要的是在右上方的 **Actions** 菜单下的 “System ID”。
|
||||
首次启动 Syncthing 时,它将启动 Web 浏览器以配置守护程序。第一台计算机上没有太多要做,但是这是一个很好的机会来介绍一下用户界面 (UI)。最重要的是在右上方的 “Actions” 菜单下的 “System ID”。
|
||||
|
||||
![Machine ID][5]
|
||||
|
||||
设置第一台计算机后,请在第二台计算机上重复安装。在 UI 中,右下方将显示一个按钮,名为 **Add Remote Device**。单击按钮,你将会看到一个要求输入**设备 ID 和设备名**的框。从第一台计算机上复制并粘贴**设备 ID**,然后单击 **Save**。
|
||||
设置第一台计算机后,请在第二台计算机上重复安装。在 UI 中,右下方将显示一个按钮,名为 “Add Remote Device”。单击该按钮,你将会看到一个要求输入 “Device ID and a Name” 的框。从第一台计算机上复制并粘贴 “Device ID”,然后单击 “Save”。
|
||||
|
||||
你应该会在第一台上看到一个请求添加第二台的弹出窗口。接受后,新机器将显示在第一台机器的右下角。与第二台计算机共享默认目录。单击 **Default Folder**,然后单击 **Edit** 按钮。弹出窗口的顶部有四个链接。单击 **Sharing**,然后选择第二台计算机。单击 **Save**,然后查看第二台计算机。你会看到一个接受共享目录的提示。接受后,它将开始在两台计算机之间同步文件。
|
||||
你应该会在第一台上看到一个请求添加第二台的弹出窗口。接受后,新机器将显示在第一台机器的右下角。与第二台计算机共享默认目录。单击 “Default Folder”,然后单击 “Edit” 按钮。弹出窗口的顶部有四个链接。单击 “Sharing”,然后选择第二台计算机。单击 “Save”,然后查看第二台计算机。你会看到一个接受共享目录的提示。接受后,它将开始在两台计算机之间同步文件。
|
||||
|
||||
![Sharing a directory in Syncthing][6]
|
||||
|
||||
测试从一台计算机上复制文件到默认目录(**/your/home/Share**)。它应该很快会在另一台上出现。
|
||||
测试从一台计算机上复制文件到默认目录(“/你的家目录/Share”)。它应该很快会在另一台上出现。
|
||||
|
||||
你可以根据需要添加任意数量的目录,这非常方便。如你在第一张图中所看到的,我有一个用于保存配置的 **myconfigs** 文件夹。当我买了一台新机器时,我只需安装 Syncthing,如果我在一台机器上调整了配置,我不必更新所有,它会自动更新。
|
||||
你可以根据需要添加任意数量的目录,这非常方便。如你在第一张图中所看到的,我有一个用于保存配置的 `myconfigs` 文件夹。当我买了一台新机器时,我只需安装 Syncthing,如果我在一台机器上调整了配置,我不必更新所有,它会自动更新。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@ -49,7 +51,7 @@ via: https://opensource.com/article/20/1/sync-files-syncthing
|
||||
作者:[Kevin Sonney][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
@ -0,0 +1,71 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (It’s the end for Windows Server 2008 support)
|
||||
[#]: via: (https://www.networkworld.com/article/3513980/it-s-the-end-for-windows-server-2008-support.html)
|
||||
[#]: author: (Andy Patrizio https://www.networkworld.com/author/Andy-Patrizio/)
|
||||
|
||||
It’s the end for Windows Server 2008 support
|
||||
======
|
||||
Microsoft recommends migrating Server 2008 workloads to Azure cloud services while enterprises modernize their apps for Windows Server 2016 or 2019 deployments.
|
||||
PaulFleet / Getty Images / Microsoft
|
||||
|
||||
This week's Patch Tuesday marked the end of the line for both Windows 7 and Windows Server 2008 (and 2008 R2). No more fixes will be issued for the two aged operating systems, unless you purchase a pricey extended service license.
|
||||
|
||||
On the Windows 7 front, Microsoft has done a good job getting Windows 10 deployed through its aggressive (perhaps too aggressive) upgrade program. According to StatCounter, Windows 10 now accounts for 65% of the [worldwide desktop Windows market share][1], and Windows 7 is down to 27%.
|
||||
|
||||
**RELATED:** [What to know before upgrading to Windows Server 2019][2]
|
||||
|
||||
But while Windows 7 has gotten all the attention, Server 2008 actually has a larger share of holdouts, and in some ways, its end-of-life milestone is more significant. At last July’s Inspire show, a Microsoft executive said in an interview with cloud storage provider and Microsoft partner Carbonite that [60% of its current Windows Server][3] installed base was running Server 2008, accounting for 24 million instances.
|
||||
|
||||
[][4]
|
||||
|
||||
BrandPost Sponsored by HPE
|
||||
|
||||
[Take the Intelligent Route with Consumption-Based Storage][4]
|
||||
|
||||
Combine the agility and economics of HPE storage with HPE GreenLake and run your IT department with efficiency.
|
||||
|
||||
“There are a lot [of customers sticking with Server 2008],” says analyst Tim Crawford of research and advisory firm [AVOA][5]. “You could categorize them into those that either a) use functions specific to WS2008, and b) those that use a version of an application that is only compatible with WS2008. Upgrading is often easier said than done. Especially if the application is a custom app with lots of tentacles.”
|
||||
|
||||
Server 2008 is based on the Windows Vista codebase, which should be reason alone to jettison it. But Windows Server 2016 and Windows Server 2019 are built on Windows 10, which means apps heavily dependent on the OS ecosystem might be hard to move since the internals are so different.
|
||||
|
||||
“I do work with folks that are still running Windows Server 2008. They understand the ramifications of EOL for support. But most are in a predicament where they aren’t able to move the applications for a number of reasons, including application compatibility, location, etc.," Crawford says.
|
||||
|
||||
For those apps that are challenging to move, he recommends isolating the system as much as possible to protect it, and putting in a plan to do what is needed to the applications to prepare them for movement as quickly as possible.
|
||||
|
||||
Microsoft offers and recommends [Azure migration][6], so Server 2008 apps can [run in an Azure instance][7] while they are modernized for Server 2019 and then deployed on premises.
|
||||
|
||||
Migration should be the paramount effort, because if you are running Server 2008 then you're using hardware that's at least eight years old and potentially 12 years old. That’s ancient in technology terms, and if nothing else, the hardware is going to fail.
|
||||
|
||||
One of the headaches for admins is you cannot migrate Server 2008 directly to 2016 or 2019. You have to upgrade to Server 2012 as an intermediate step. So you are better off biting the bullet and migrating the apps to 2019 rather than spending time on two OS migrations.
|
||||
|
||||
Microsoft has provided [resources][8] for Server 2008 users, including a migration guide and help moving to Azure.
|
||||
|
||||
Join the Network World communities on [Facebook][9] and [LinkedIn][10] to comment on topics that are top of mind.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.networkworld.com/article/3513980/it-s-the-end-for-windows-server-2008-support.html
|
||||
|
||||
作者:[Andy Patrizio][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.networkworld.com/author/Andy-Patrizio/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://gs.statcounter.com/os-version-market-share/windows/desktop/worldwide#monthly-201807-201908
|
||||
[2]: https://www.networkworld.com/article/3512020/what-to-know-before-upgrading-from-windows-server-2016-to-server-2019.html
|
||||
[3]: https://www.carbonite.com/blog/article/2019/07/schuster-azure-migration-and-office-365-top-partner-opportunities
|
||||
[4]: https://www.networkworld.com/article/3440100/take-the-intelligent-route-with-consumption-based-storage.html?utm_source=IDG&utm_medium=promotions&utm_campaign=HPE21620&utm_content=sidebar ( Take the Intelligent Route with Consumption-Based Storage)
|
||||
[5]: https://avoa.com/
|
||||
[6]: https://cloudblogs.microsoft.com/windowsserver/2019/12/17/protect-workloads-still-running-on-windows-server-2008-and-2008-r2/
|
||||
[7]: https://www.networkworld.com/article/3300165/microsoft-lures-win-server-2008-users-toward-azure.html
|
||||
[8]: https://www.microsoft.com/en-us/cloud-platform/windows-server-2008
|
||||
[9]: https://www.facebook.com/NetworkWorld/
|
||||
[10]: https://www.linkedin.com/company/network-world
|
@ -0,0 +1,160 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (4 core skills to level-up your tech career in 2020)
|
||||
[#]: via: (https://opensource.com/article/20/1/core-skills-tech-career)
|
||||
[#]: author: (Dawn Parzych https://opensource.com/users/dawnparzych)
|
||||
|
||||
4 core skills to level-up your tech career in 2020
|
||||
======
|
||||
There is one category of skill you should focus on to advance your
|
||||
career this year. Here's how.
|
||||
![Two hands holding a resume with computer, clock, and desk chair ][1]
|
||||
|
||||
We do a lot to level-up our careers. We learn new programming languages; we take on new projects at work; we work on side projects on the weekend; we contribute to open source communities. What if I were to tell you that, while these activities are helpful, there is one set of skills you should focus on if you truly want to advance your career.
|
||||
|
||||
These skills go by many names, such as soft skills, non-technical skills, leadership skills, and people skills. Calling them soft or non-technical skills leads to the mistaken idea that they are easy. For some, these skills are incredibly difficult. Calling them leadership skills makes people think they don't need to put effort into developing them if they don't want to be a leader.
|
||||
|
||||
I prefer to call them core or functional skills. These skills are part of the core of what makes us human, and it is hard to function without them.
|
||||
|
||||
When we have these skills, we can:
|
||||
|
||||
* Communicate with others
|
||||
* Collaborate and work with others
|
||||
* Solve problems
|
||||
* Understand and share the feelings of others
|
||||
* Use time effectively or productively
|
||||
|
||||
|
||||
|
||||
These skills are part of what makes us human, and everything in software is about humans. Humans are reviewing your code. Humans are installing or using the application you are writing.
|
||||
|
||||
If these skills are so essential, why do we often dismiss them in favor of more "technical" skills and give them a bad rap? This isn't about focusing on one versus the other. Both are important and relevant.
|
||||
|
||||
### Mindset and biases
|
||||
|
||||
Our biases and mindset contribute to the importance we place on functional skills. Bias isn't a bad thing. There are [175 biases][2] that exist to help our brains combat four problems:
|
||||
|
||||
* We have too much information to process.
|
||||
* There's not enough meaning in the information we receive.
|
||||
* There's not enough time to process information.
|
||||
* We can't remember everything. Our memory is finite.
|
||||
|
||||
|
||||
|
||||
One bias that sneaks in when it comes to assessing our skills is the Dunning-Kruger effect. We mistakenly assess our abilities as more exceptional than they are, which comes from an inability to recognize our own faults. You may think you know what you are doing when you don't because of the Dunning-Kruger effect. You think you are managing your time effectively, but in reality, you are working nights and weekends to get caught up. Yes, the work is getting completed, but at what cost? Working non-stop can lead to burnout or a decline in health.
|
||||
|
||||
Another factor is your [mindset][3]. Do you have a growth mindset or a fixed mindset when it comes to learning a new skill? People with a fixed mindset believe that abilities are innate and can't be improved. Those with a growth mindset believe there is room for improvement, and you can improve any skill with practice.
|
||||
|
||||
These statements reflect a fixed mindset:
|
||||
|
||||
* "I'm just not a people person."
|
||||
* "They're a natural-born leader."
|
||||
|
||||
|
||||
|
||||
You're not born with the ability to speak or write. You learn these skills over time. The same goes for the core and functional skills important for developers.
|
||||
|
||||
### Communication
|
||||
|
||||
> "Over time I've learned the biggest source of failure is often due to people and teams. A lack of communication and coordination can cause serious problems."
|
||||
> — Laurie Barth, [_How architecture improved my coding skills_][4]
|
||||
|
||||
Communication includes verbal, non-verbal, and written communication. Failures along any of these can cause serious problems. Communication failures in tech look like:
|
||||
|
||||
* Delays in resolving incidents
|
||||
* Redesigning a feature
|
||||
* Scope creep
|
||||
* Lack of meaningful comments on pull requests (PRs)—these can be especially impactful to junior engineers
|
||||
* Unnecessary conflicts and lack of alignment
|
||||
* Delivering above or below expectations
|
||||
|
||||
|
||||
|
||||
Cultural norms and personal preferences impact communication. Everybody has a preferred method of communicating, whether that is via email, face-to-face, Slack messages, phone, text, etc. Think about the cultural norms regarding communication in your workplace. Do they match your preferred method of communicating? If there is a mismatch, problems may arise.
|
||||
|
||||
If you're a manager, do you know your direct reports' preferred communication style, or do you just utilize your preferred method? If a direct report prefers email so they can have some time to think before responding and you prefer face-to-face communication, a quick Slack message asking them to come to your office can cause unnecessary anxiety.
|
||||
|
||||
### Empathy
|
||||
|
||||
> "Empathy is much harder than we think… But to build empathy we need to slow down."
|
||||
> —Andrew Tenzer and Ian Murray, [_The empathy delusion_][5]
|
||||
|
||||
Empathy is one of the most important skills you can learn. Empathy is our ability to understand and share the feelings of others. We feel more connected to one another because of empathy.
|
||||
|
||||
There are four attributes of empathy:
|
||||
|
||||
* Seeing another person's perspective
|
||||
* Being non-judgmental
|
||||
* Recognizing emotions in other people
|
||||
* Communicating your understanding of another person's feelings
|
||||
|
||||
|
||||
|
||||
Communication and empathy are closely tied. To communicate effectively, you need to listen. To listen effectively, you need empathy. Instead of listening to what a colleague is saying, we usually think about how to best respond. As the adage goes, you have two ears and one mouth for a reason; you should be listening twice as often as you speak.
|
||||
|
||||
When you show empathy towards another person, you are not minimizing their thoughts, feelings, or experiences. Instead of using comments like "it could be worse" or "at least…" use phrases like "that sounds horrible," "I can't imagine how you must feel," or "I'm here for you, how can I help?"
|
||||
|
||||
### Get ready to level-up
|
||||
|
||||
Improving on a skill takes time, but we often give up while we are learning once [impostor syndrome][6] kicks in. It takes years of practice to perfect something, and even with years of practice, you won't be perfect. You will make mistakes. When learning a new skill or improving on an existing skill, mastery—not perfection—should be the goal. Perfection implies there is no room for improvement; mastery indicates learning a skill is an ongoing journey, and there is room to improve.
|
||||
|
||||
You don't want to be a perfect communicator. You want to be a master communicator. Even the most experienced public speakers make mistakes. If you aim for perfection, you will be disappointed.
|
||||
|
||||
To improve a skill, you need to schedule time to practice. But not just any type of practice; to master a skill, use deliberate practice. Deliberate practice has five main components:
|
||||
|
||||
1. Create a specific goal.
|
||||
2. Break the goal down into small steps.
|
||||
3. Get feedback from a master.
|
||||
4. Step out of your comfort zone.
|
||||
5. Stay motivated.
|
||||
|
||||
|
||||
|
||||
To illustrate this process, say you have a goal of presenting at a conference, but you aren't a confident public speaker. What are some small steps you can take to practice?
|
||||
|
||||
* Identify and reduce the use of filler words like "um," "ah," or "you know."
|
||||
* Make eye contact when speaking with others or let people know why you don't.
|
||||
* Control mannerisms like fidgeting with your hands or nodding your head while talking.
|
||||
* Incorporate appropriate pauses.
|
||||
|
||||
|
||||
|
||||
Feedback is a necessary part of practicing. Seek out others to provide you with feedback. A great way to step out of your comfort zone and get feedback from master public speakers is to sign up for Toastmasters. This can also help you stay motivated as you work through the speeches towards becoming a Distinguished Toastmaster.
|
||||
|
||||
You can apply this same process to any skill you are looking to master.
|
||||
|
||||
### Where to learn more
|
||||
|
||||
If you want to learn more about empathy and communication so you can level up your career, check out these resources:
|
||||
|
||||
* [Communicating with empathy][7] course by Sharon Steed
|
||||
* [_Deliberate practice: Your pathway to growth and mastery_][8] by Habits at Work
|
||||
* [_Want to be more empathetic? Avoid these 7 responses_][9] by Laura Click
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/1/core-skills-tech-career
|
||||
|
||||
作者:[Dawn Parzych][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/dawnparzych
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/resume_career_document_general.png?itok=JEaFL2XI (Two hands holding a resume with computer, clock, and desk chair )
|
||||
[2]: https://medium.com/better-humans/cognitive-bias-cheat-sheet-55a472476b18
|
||||
[3]: https://www.penguinrandomhouse.com/books/44330/mindset-by-carol-s-dweck-phd/
|
||||
[4]: https://dev.to/laurieontech/how-architecture-improved-my-coding-skills-21e
|
||||
[5]: https://www.reachsolutions.co.uk/sites/default/files/2019-07/Reach%20Solutions%20The%20Empathy%20Delusion%20V2.pdf
|
||||
[6]: https://en.wikipedia.org/wiki/Impostor_syndrome
|
||||
[7]: https://www.lynda.com/Business-Skills-tutorials/Communicating-Empathy/534584-2.html
|
||||
[8]: https://habitsatwork.com/blog/deliberate-practice
|
||||
[9]: https://medium.com/@lauraclick/want-to-be-more-empathetic-avoid-these-7-responses-21bb52d5d2ad
|
385
sources/tech/20200116 Automating Helm deployments with Bash.md
Normal file
385
sources/tech/20200116 Automating Helm deployments with Bash.md
Normal file
@ -0,0 +1,385 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Automating Helm deployments with Bash)
|
||||
[#]: via: (https://opensource.com/article/20/1/automating-helm-deployments-bash)
|
||||
[#]: author: (Darin London https://opensource.com/users/dmlond)
|
||||
|
||||
Automating Helm deployments with Bash
|
||||
======
|
||||
This Bash script enables developers to focus on their code rather than
|
||||
the deployment logic in each project.
|
||||
![Person using a laptop][1]
|
||||
|
||||
Some of our applications are hosted in a [Kubernetes][2] cluster, and we use GitLab Continuous Integration (CI) to automate deployments and Helm 2 to deploy our applications. Helm charts enable the storage of templates of Kubernetes object YAML files with variables that can be programmatically set from command-line arguments passed when the chart is used during deployments. This allows us to store critical secrets in GitLab-protected environment variables or in Hashicorp Vault and use them within the CI deployment job.
|
||||
|
||||
Our deployment job uses a [Bash script to run the deployment process][3]. This Bash script presents a number of features that are valuable for use within a CI/CD environment:
|
||||
|
||||
1. It facilitates use outside of the CI/CD environment. GitLab CI and other CI systems store job steps as lines of executable shell code in a "script" section of a CI text file (.gitlab-ci.yml, for example). While this is useful to ensure basic executable steps can be stored without external dependencies, it prevents developers from using the same code in testing or manual deployment scenarios. In addition, many advanced features of the Bash system cannot be easily used in these script sections.
|
||||
2. It facilitates unit testing of important deployment processes. None of the CI systems provide a way of testing whether deployment logic performs as expected. Carefully constructed [Bash scripts can be unit tested with BATS][4].
|
||||
3. It facilitates reuse of individual functions within the script. The last section uses a guard clause, **if [[ "${BASH_SOURCE[0]}" == "${0}" ]]**, which prevents the **run_main** function from being called when the script is not being executed. This allows the script to be sourced, which then allows users to make use of the many useful individual functions within it. This is crucial for proper BATS testing.
|
||||
4. It uses environment variables to protect sensitive information and make the script reusable across many projects and project application environments. GitLab CI makes many of these environment variables available when run by a GitLab CI runner. These must be manually set before using the script outside GitLab CI.
|
||||
|
||||
|
||||
|
||||
The script performs all tasks required to deploy a Helm chart for an application to Kubernetes and waits for the deployment to be ready using kubectl and Helm. Helm runs with a local Tiller installation instead of running Tiller in the Kubernetes cluster. The Kubernetes **HELM_USER** and **HELM_PASSWORD** are used to log into the Kubernetes **CLUSTER_SERVER** and **PROJECT_NAMESPACE**. Tiller is started, Helm is initialized in client-only mode, and its repo is updated. The template is linted with Helm to ensure that syntax errors have not been accidentally committed. The template is then deployed in declarative mode, using **helm upgrade --install**. Helm waits for the deployment to be ready using the **\--wait flag**.
|
||||
|
||||
The script ensures that certain template variables are set during the deployment and allows special project-specific variables to be specified in the GitLab CI **PROJECT_SPECIFIC_DEPLOY_ARGS** environment variable. All environment variables required in the deployment are checked early in the script execution, and the script exits with a non-zero exit status if any are missing.
|
||||
|
||||
This script has been used in multiple GitLab CI-hosted projects. It has helped us focus on our code rather than the deployment logic in each project.
|
||||
|
||||
### The script
|
||||
|
||||
|
||||
```
|
||||
#!/bin/bash
|
||||
|
||||
# MIT License
|
||||
#
|
||||
# Copyright (c) 2019 Darin London
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
log_level_for()
|
||||
{
|
||||
case "${1}" in
|
||||
"error")
|
||||
echo 1
|
||||
;;
|
||||
|
||||
"warn")
|
||||
echo 2
|
||||
;;
|
||||
|
||||
"debug")
|
||||
echo 3
|
||||
;;
|
||||
|
||||
"info")
|
||||
echo 4
|
||||
;;
|
||||
*)
|
||||
echo -1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
current_log_level()
|
||||
{
|
||||
log_level_for "${LOG_LEVEL}"
|
||||
}
|
||||
|
||||
error()
|
||||
{
|
||||
[ $(log_level_for "error") -le $(current_log_level) ] && echo "${1}" >&2
|
||||
}
|
||||
|
||||
warn()
|
||||
{
|
||||
[ $(log_level_for "warn") -le $(current_log_level) ] && echo "${1}" >&2
|
||||
}
|
||||
|
||||
debug()
|
||||
{
|
||||
[ $(log_level_for "debug") -le $(current_log_level) ] && echo "${1}" >&2
|
||||
}
|
||||
|
||||
info()
|
||||
{
|
||||
[ $(log_level_for "info") -le $(current_log_level) ] && echo "${1}" >&2
|
||||
}
|
||||
|
||||
check_required_environment() {
|
||||
local required_env="${1}"
|
||||
|
||||
for reqvar in $required_env
|
||||
do
|
||||
if [ -z "${!reqvar}" ]
|
||||
then
|
||||
error "missing ENVIRONMENT ${reqvar}!"
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
check_default_environment() {
|
||||
local required_env="${1}"
|
||||
|
||||
for varpair in $required_env
|
||||
do
|
||||
local manual_environment=$(echo "${varpair}" | cut -d':' -f1)
|
||||
local default_if_not_set=$(echo "${varpair}" | cut -d':' -f2)
|
||||
if [ -z "${!manual_environment}" ] && [ -z "${!default_if_not_set}" ]
|
||||
then
|
||||
error "missing default ENVIRONMENT, set ${manual_environment} or ${default_if_not_set}!"
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
dry_run() {
|
||||
[ ${DRY_RUN} ] && info "skipping for dry run" && return
|
||||
return 1
|
||||
}
|
||||
|
||||
init_tiller() {
|
||||
info "initializing local tiller"
|
||||
dry_run && return
|
||||
|
||||
export TILLER_NAMESPACE=$PROJECT_NAMESPACE
|
||||
export HELM_HOST=localhost:44134
|
||||
# <https://rimusz.net/tillerless-helm/>
|
||||
# run tiller locally instead of in the cluster
|
||||
tiller --storage=secret &
|
||||
export TILLER_PID=$!
|
||||
sleep 1
|
||||
kill -0 ${TILLER_PID}
|
||||
if [ $? -gt 0 ]
|
||||
then
|
||||
error "tiller not running!"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
init_helm() {
|
||||
info "initializing helm"
|
||||
dry_run && return
|
||||
|
||||
helm init --client-only
|
||||
if [ $? -gt 0 ]
|
||||
then
|
||||
error "could not initialize helm"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
init_helm_with_tiller() {
|
||||
init_tiller || return 1
|
||||
init_helm || return 1
|
||||
info "updating helm client repository information"
|
||||
dry_run && return
|
||||
helm repo update
|
||||
if [ $? -gt 0 ]
|
||||
then
|
||||
error "could not update helm repository information"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
decommission_tiller() {
|
||||
if [ -n "${TILLER_PID}" ]
|
||||
then
|
||||
kill ${TILLER_PID}
|
||||
if [ $? -gt 0 ]
|
||||
then
|
||||
return
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
check_required_deploy_arg_environment() {
|
||||
[ -z "${PROJECT_SPECIFIC_DEPLOY_ARGS}" ] && return
|
||||
for reqvar in ${PROJECT_SPECIFIC_DEPLOY_ARGS}
|
||||
do
|
||||
if [ -z ${!reqvar} ]
|
||||
then
|
||||
error "missing Deployment ENVIRONMENT ${reqvar} required!"
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
project_specific_deploy_args() {
|
||||
[ -z "${PROJECT_SPECIFIC_DEPLOY_ARGS}" ] && echo "" && return
|
||||
|
||||
extraArgs=''
|
||||
for deploy_arg_key in ${PROJECT_SPECIFIC_DEPLOY_ARGS}
|
||||
do
|
||||
extraArgs="${extraArgs} --set $(echo "${deploy_arg_key}" | sed 's/__/\\./g' | tr '[:upper:]' '[:lower:]')=${!deploy_arg_key}"
|
||||
done
|
||||
|
||||
echo "${extraArgs}"
|
||||
}
|
||||
|
||||
check_required_cluster_login_environment() {
|
||||
check_required_environment "HELM_TOKEN HELM_USER PROJECT_NAMESPACE CLUSTER_SERVER" || return 1
|
||||
}
|
||||
|
||||
cluster_login() {
|
||||
info "authenticating ${HELM_USER} in ${PROJECT_NAMESPACE}"
|
||||
dry_run && return
|
||||
|
||||
kubectl config set-cluster ci_kube --server="${CLUSTER_SERVER}" || return 1
|
||||
kubectl config set-credentials "${HELM_USER}" --token="${HELM_TOKEN}" || return 1
|
||||
kubectl config set-context ${PROJECT_NAMESPACE}-deploy --cluster=ci_kube --namespace=${PROJECT_NAMESPACE} --user=${HELM_USER} || return 1
|
||||
kubectl config use-context ${PROJECT_NAMESPACE}-deploy || return 1
|
||||
}
|
||||
|
||||
lint_template() {
|
||||
info "linting template"
|
||||
dry_run && return
|
||||
|
||||
helm lint ${CI_PROJECT_DIR}/helm-chart/${CI_PROJECT_NAME}
|
||||
}
|
||||
|
||||
check_required_image_pull_environment() {
|
||||
if [ "${CI_PROJECT_VISIBILITY}" == "public" ]
|
||||
then
|
||||
check_required_environment "CI_REGISTRY CI_DEPLOY_USER CI_DEPLOY_PASSWORD" || return 1
|
||||
fi
|
||||
}
|
||||
|
||||
image_pull_settings() {
|
||||
if [ "${CI_PROJECT_VISIBILITY}" == "public" ]
|
||||
then
|
||||
echo ""
|
||||
else
|
||||
echo "--set registry.root=${CI_REGISTRY} --set registry.secret.username=${CI_DEPLOY_USER} --set registry.secret.password=${CI_DEPLOY_PASSWORD}"
|
||||
fi
|
||||
}
|
||||
|
||||
deployment_name() {
|
||||
if [ -n "${DEPLOYMENT_NAME}" ]
|
||||
then
|
||||
echo "${DEPLOYMENT_NAME}"
|
||||
else
|
||||
echo "${CI_ENVIRONMENT_SLUG}-${CI_PROJECT_NAME}"
|
||||
fi
|
||||
}
|
||||
|
||||
deploy_template() {
|
||||
info "deploying $(deployment_name) from template"
|
||||
if dry_run
|
||||
then
|
||||
info "helm upgrade --force --recreate-pods --debug --set image.repository=${CI_REGISTRY_IMAGE}/${CI_PROJECT_NAME} --set image.tag=${CI_COMMIT_SHORT_SHA} --set environment=${CI_ENVIRONMENT_NAME} --set-string git_commit=${CI_COMMIT_SHORT_SHA} --set git_ref=${CI_COMMIT_REF_SLUG} --set ci_job_id=${CI_JOB_ID} $(environment_url_settings) $(image_pull_settings) $(project_specific_deploy_args) --wait --install $(deployment_name) ${CI_PROJECT_DIR}/helm-chart/${CI_PROJECT_NAME}"
|
||||
else
|
||||
helm upgrade --force --recreate-pods --debug \
|
||||
--set image.repository="${CI_REGISTRY_IMAGE}/${CI_PROJECT_NAME}" \
|
||||
--set image.tag="${CI_COMMIT_SHORT_SHA}" \
|
||||
--set environment="${CI_ENVIRONMENT_NAME}" \
|
||||
--set-string git_commit="${CI_COMMIT_SHORT_SHA}" \
|
||||
--set git_ref="${CI_COMMIT_REF_SLUG}" \
|
||||
--set ci_job_id="${CI_JOB_ID}" \
|
||||
$(image_pull_settings) \
|
||||
$(project_specific_deploy_args) \
|
||||
--wait \
|
||||
--install $(deployment_name) ${CI_PROJECT_DIR}/helm-chart/${CI_PROJECT_NAME}
|
||||
fi
|
||||
}
|
||||
|
||||
get_pods() {
|
||||
kubectl get pods -l ci_job_id="${CI_JOB_ID}"
|
||||
}
|
||||
|
||||
watch_deployment() {
|
||||
local watch_deployment=$(deployment_name)
|
||||
if [ -n "${WATCH_DEPLOYMENT}" ]
|
||||
then
|
||||
watch_deployment="${WATCH_DEPLOYMENT}"
|
||||
fi
|
||||
info "waiting until deployment ${watch_deployment} is ready"
|
||||
dry_run && return
|
||||
|
||||
kubectl rollout status deployment/${watch_deployment} -w || return 1
|
||||
sleep 5
|
||||
get_pods || return 1
|
||||
# see what has been deployed
|
||||
kubectl describe deployment -l app=${CI_PROJECT_NAME},environment=${CI_ENVIRONMENT_NAME},git_commit=${CI_COMMIT_SHORT_SHA} || return 1
|
||||
if [ -n "${CI_ENVIRONMENT_URL}" ]
|
||||
then
|
||||
kubectl describe service -l app=${CI_PROJECT_NAME},environment=${CI_ENVIRONMENT_NAME} || return 1
|
||||
kubectl describe route -l app=${CI_PROJECT_NAME},environment=${CI_ENVIRONMENT_NAME} || return 1
|
||||
fi
|
||||
}
|
||||
|
||||
run_main() {
|
||||
check_required_environment "CI_PROJECT_NAME CI_PROJECT_DIR CI_COMMIT_REF_SLUG CI_REGISTRY_IMAGE CI_ENVIRONMENT_NAME CI_JOB_ID CI_COMMIT_SHORT_SHA" || return 1
|
||||
check_default_environment "WATCH_DEPLOYMENT:CI_ENVIRONMENT_SLUG" || return 1
|
||||
check_required_deploy_arg_environment || return 1
|
||||
check_required_cluster_login_environment || return 1
|
||||
check_required_image_pull_environment || return 1
|
||||
cluster_login
|
||||
if [ $? -gt 0 ]
|
||||
then
|
||||
error "could not login kubectl"
|
||||
return 1
|
||||
fi
|
||||
|
||||
init_helm_with_tiller
|
||||
if [ $? -gt 0 ]
|
||||
then
|
||||
error "could not initialize helm"
|
||||
return 1
|
||||
fi
|
||||
|
||||
lint_template
|
||||
if [ $? -gt 0 ]
|
||||
then
|
||||
error "linting failed"
|
||||
return 1
|
||||
fi
|
||||
|
||||
deploy_template
|
||||
if [ $? -gt 0 ]
|
||||
then
|
||||
error "could not deploy template"
|
||||
return 1
|
||||
fi
|
||||
|
||||
watch_deployment
|
||||
if [ $? -gt 0 ]
|
||||
then
|
||||
error "could not watch deployment"
|
||||
return 1
|
||||
fi
|
||||
|
||||
decommission_tiller
|
||||
info "ALL Complete!"
|
||||
return
|
||||
}
|
||||
|
||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]
|
||||
then
|
||||
run_main
|
||||
if [ $? -gt 0 ]
|
||||
then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
```
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/1/automating-helm-deployments-bash
|
||||
|
||||
作者:[Darin London][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/dmlond
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/laptop_screen_desk_work_chat_text.png?itok=UXqIDRDD (Person using a laptop)
|
||||
[2]: https://opensource.com/resources/what-is-kubernetes
|
||||
[3]: https://gist.github.com/dmlond/016ff7c3757fee00f9d02e36e6c0c298
|
||||
[4]: https://opensource.com/article/19/2/testing-bash-bats
|
Loading…
Reference in New Issue
Block a user