2020年2月13日 星期四

雲端上動態延展的架構下,如何不影響運作的情況下,持續的進行作業系統的更新,以AWS平台架構為例

在以往的運作下,如果以負載平衡的情況下進行,假設有8台電腦進行網站的負載,可以將流量導向其他台後,再將沒有流量的電腦先進行下線,然後逐一進行更新後,再將電腦重新加入進行服務。

但在雲端上,為了動態的調整所需的資源,我們可以透過 AWS Auto Scaling 的服務,自動的依據負據來動態的增加或減少伺服器的數量,但這時候問題就來了,該如何在這樣的架構下進行平日的作業系統維護與底層映像檔的更換。

在與許多人討論過,常見的方法都是將目前自行維護的映像檔再建立一台新的伺服器,然後再安裝作業系統的更新後,再作成映像檔,然後再抽換 Auto Scaling 服務中對應的映像檔。但是這樣一來通常都需要安排特定停機時間進行,而且需要花費多人來進行相關的作業。

上述的動作如果我們希望可以全部自動進行時,並儘可能的減少人工的作業,因為這種持續性的動作,人為的進行總是有疏忽的時候,讓自動的進行,才可以讓整個系統的可靠性更高。

本篇主要介紹到,希望可以透過AWS提供的眾多服務進行整合,藉以達到此需求,其實我介紹的這個方法在AWS的官網中也有介紹到,但本篇加以進行整合,然後我也特別將官網未提到的方法進行整合,並且加入排程的部份,所以我會在此文章中完整的說明並介紹給大家,也讓大家可以嘗試將這個方法導入您的環境中。

在建立前我先初步的介紹,基本上,主要是透過 SSM Automation 的服務,將指定的映像檔建立成一台新的伺服器,然後透過 SSM Run Command 進行作業系統的更新,最後再關閉伺服器,然後再進行新的映像檔的制作,最後再進行 SSM Parameter Store 參數的更新與 Auto Scaling Group 的底層映像檔的更新,基本上你可以透過下列的步驟逐一的進行即可完成初步的建置。

步驟一:建立一個Auto Scaling Group


這部份,由於後面的 AWS Lambda 程式是以 Launch Configuration 為主,所以我們也是先建立一個 Launch Configuration,後續上程式也會進行這部份的新增與抽換。


選擇預設的作業系統,由於我預期是一個全新的作業系統,所以我以 AWS 上預設的 Windows Server 2016 當成是基底進行,當然如果你有自已管理的映像檔的話,你也可以自行選擇。

建立完成範本後,再進行 Auto Scaling group 的新增,在子網路的部份,建議將目前所有的子網路區段都加入。


另外在自動成長的規則部份,我這這邊是設定為當 CPU 的使用率超過50%的時候並且超過300秒,就進行自動成長的動作。


步驟二:請先建立一個參數於 Parameter Store 中,藉以記錄目前最後更新映像檔編號 (AMI ID).


登入 Systems Manager 中心,並建立下列的參數,如下圖所示,另外名稱的部份請確認為 "latestAmi" 因為後續會使用到。

而參數中的值,請填入你目前最新維護的映像檔編號,如我的測試,我是以目前此區域中預設最新的 Windows Server 2016為此值的設定。


步驟三:建立一個 AWS Lambda執行時進行的IAM角色


登入 AWS IAM -> Roles,建立一個新的角色,並且依照下列的圖示加入相對應的權限。
AutoScalingFullAccess
AmazonSSMFullAccess
AWSLambdaExecute

此步驟中,名稱設定為:SSMAutoUpdateRoleForLambda


步驟四:建立一個 Lambda Function 藉以進行更新 Auto Scaling Group 和步驟一中建立的參數。


登入 AWS Lambda -> Create Function,如下列的圖示加入一個相對應的 Lambda Function


其中在 Execution role的部份,請選擇在步驟二中建立的 IAM 角色,建立完成後,請將下列的程式碼貼入 Function Code 的區域中存檔即可。
from __future__ import print_function

import json
import datetime
import time
import boto3

print('Loading function')


def lambda_handler(event, context):
print("Received event: " + json.dumps(event, indent=2))

# get autoscaling client
client = boto3.client('autoscaling')

# get object for the ASG we're going to update, filter by name of target ASG response = client.describe_auto_scaling_groups(AutoScalingGroupNames=[event['targetASG']])

if not response['AutoScalingGroups']:
return 'No such ASG'

# get name of InstanceID in current ASG that we'll use to model new Launch Configuration after sourceInstanceId = response.get('AutoScalingGroups')[0]['Instances'][0]['InstanceId']

# create LC using instance from target ASG as a template, only diff is the name of the new LC and new AMI
timeStamp = time.time()
timeStampString = datetime.datetime.fromtimestamp(timeStamp).strftime('%Y-%m-%d %H-%M-%S')
newLaunchConfigName = 'LC '+ event['newAmiID'] + ' ' + timeStampString
client.create_launch_configuration(
InstanceId = sourceInstanceId,
LaunchConfigurationName=newLaunchConfigName,
ImageId= event['newAmiID'] )

#Updates an SSM parameter
# get SSM client
client2 = boto3.client('ssm')
parameterName = 'latestAmi'

#confirm parameter exists before updating it
response2 = client2.describe_parameters(
Filters=[
{
'Key': 'Name',
'Values': [ parameterName ]
},
]
)

if not response2['Parameters']:
print('No such parameter')
return 'SSM parameter not found.'

#if parameter has a Description field, update it PLUS the Value
if 'Description' in response2['Parameters'][0]:
description = response2['Parameters'][0]['Description']

response2 = client2.put_parameter(
Name=parameterName,
Value=event['newAmiID'],
Description=description,
Type='String',
Overwrite=True
)

#otherwise just update Value
else:
response2 = client2.put_parameter(
Name=parameterName,
Value=event['newAmiID'],
Type='String',
Overwrite=True
)

# update ASG to use new LC
response = client.update_auto_scaling_group(AutoScalingGroupName = event['targetASG'],LaunchConfigurationName = newLaunchConfigName)

return 'Updated ASG `%s` with new launch configuration `%s` which includes AMI `%s`.' % (event['targetASG'], newLaunchConfigName, event['newAmiID'])

另外,你也可以在右上角的部份點選測試,確認是否執行正確,測試時,名稱就隨意輸入即可,另外在下列的格式中,請取代輸入你的參考值。

如同我的範例如下。
{
"newAmiID": "ami-02c8625672a43c5e0",
"targetASG": "SSM-ASG"

步驟五: 建立一個 IAM 角色設定給當執行 SSM Automation 時,所需要的權限。


登入 AWS IAM -> Roles,建立一個新的角色,並且依照下列的圖示加入相對應的權限。
AmazonSSMAutomationRole

另外再請加入一個inline policy,並允許進行AssuleRole的進行
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "*"

此步驟中,名稱設定為:SSMAutomationServiceRole

步驟六: 建立 SSM Automation Document 藉以進行作業系統的更新與進行製作新的映像檔


打開 AWS Systems Manager console -> Document -> Create automation.

請將下列的程式碼貼入後即可,但其中第三行的assuleRole請指定為在步驟四中新增的帳號,而28行的部份則是指定一個IAM role設定給伺服器使用,這個角把的新增方法,可以參考下列的連結。

About Policies for a Systems Manager Instance Profile
https://docs.aws.amazon.com/systems-manager/latest/userguide/setup-instance-profile.html
description: Systems Manager Automation Demo - Patch AMI and Update ASG
schemaVersion: '0.3'
assumeRole: 'arn:aws:iam::accountid:role/SSMAutomationServiceRole'
outputs:
- createImage.ImageId
parameters:
sourceAMIid:
type: String
description: AMI to patch
targetAMIname:
type: String
default: 'patchedAMI-{{global:DATE_TIME}}'
description: Name of new AMI
targetASG:
type: String
description: Auto Scaling group to Update
mainSteps:
- name: startInstances
action: 'aws:runInstances'
timeoutSeconds: 1200
maxAttempts: 1
onFailure: Abort
inputs:
ImageId: '{{ sourceAMIid }}'
InstanceType: m3.large
MinInstanceCount: 1
MaxInstanceCount: 1
IamInstanceProfileName: AmazonSSMManagedInstanceCore
- name: installMissingWindowsUpdates
action: 'aws:runCommand'
maxAttempts: 1
onFailure: Continue
inputs:
DocumentName: AWS-InstallWindowsUpdates
InstanceIds:
- '{{ startInstances.InstanceIds }}'
Parameters:
SeverityLevels: Important
- name: stopInstance
action: 'aws:changeInstanceState'
maxAttempts: 1
onFailure: Continue
inputs:
InstanceIds:
- '{{ startInstances.InstanceIds }}'
DesiredState: stopped
- name: createImage
action: 'aws:createImage'
maxAttempts: 1
onFailure: Continue
inputs:
InstanceId: '{{ startInstances.InstanceIds }}'
ImageName: '{{ targetAMIname }}'
NoReboot: true
ImageDescription: AMI created by EC2 Automation
- name: terminateInstance
action: 'aws:changeInstanceState'
maxAttempts: 1
onFailure: Continue
inputs:
InstanceIds:
- '{{ startInstances.InstanceIds }}'
DesiredState: terminated
- name: updateASG
action: 'aws:invokeLambdaFunction'
timeoutSeconds: 1200
maxAttempts: 1
onFailure: Abort
inputs:
FunctionName: Automation-UpdateAsg
Payload: '{"targetASG":"{{targetASG}}", "newAmiID":"{{createImage.ImageId}}"}'

建立完成後,你可以透過右上角的 Execute automation進行執行,參數的部份,可以參考下列的圖示進行。



上述的動作,單次的進行後,即可完成我們想要的動作,但是當如果需要進行排程讓上述的SSM Automation Document在固定的時間進行時,我們就需要再進行下列的動作。

在排程的部份,其實大家可以找一台固定的主機進行排程進行即可,但是我希望資訊可以完整的呈現在 AWS Conole 中,所以我這邊透過 AWS Maintenance Windows進行。

步驟七:建立 Maintenance Windows 進行排程,自動進行上述的維護動作。


登入 AWS Console -> Systems Manager -> Maintenance Windows


先輸入名稱,並設定排程時間,我這邊是設定每週日的凌晨1:00進行


設定完成後,在 Tasks 的部份,請加入一個工作排程,也就是進行執行 SSM Automation 的動作,輸入的參數如下列圖示顯示。



另外關於 sourceAMIid的部份,我是透過之前建立的參數,自動的帶入,所以格式會以 ssm 開頭,這部份再請特別的注意。


由於上述的動作整合到許多 AWS 的服務,如 AWS Auto ScalingAWS Systems ManagerAWS Lambda等功能,所以算是比較複雜的架構,但架設完成後,這樣的架構即可自動而且不斷的完成作業系統的更新並保有雲端上的彈性,所以個人非常的推薦,當然在延伸的方式上,你可以再進行更新的條件進行設定如Windows更新推出後幾天再進行安裝,或是只安裝重要更新的方式進行,這些設定都可以在 <b>SSM Systems Manager 中進行,當然如有任何問題,也歡迎提出進行討論。

參考連結:
Walkthrough: Simplify AMI Patching Using Automation, AWS Lambda, and Parameter Store
https://docs.aws.amazon.com/systems-manager/latest/userguide/automation-walk-patch-windows-ami-simplify.html

2018年1月26日 星期五

如何在AWS上進行平衡負載、網域名稱與SSL憑證(免費)的設定

在前面的文章有介紹到,該如何在Azure進行WebApp的自訂網域名稱與SSL憑證購買的方式,此次我們來介紹該如何在Amazon AWS上進行相同的動作。

關於費用的部份,在AWS中申請憑證是完全免費的,而在自訂網域名稱的部份會依照你選定的網域類型而定,如.com、.org等。

https://aws.amazon.com/tw/certificate-manager/pricing/

前導文章介紹:
如何進行自訂網域與SSL憑證購買,並綁定於App Service for Web中。
http://caryhsu.blogspot.jp/2017/02/azuressl.html


開始安裝設定:
1、Web Server安裝與設定
在這邊我準備了二台Windows on EC2進行,進行前請確認各Instance可以透過IP or DNS Name正常的存取到網站。


2、Custom Domain Name申請
2-1 請先登入Route 53,並選擇 Domain Registration

2-2 選擇 Register Domain

2-3 輸入你要註冊的Domain Name先進行檢查,確認名稱是否已有被申請。

2-4 填寫個人的資訊,這部份請特別注意在聯絡資訊的部份,由其是E-Mail與電話,後續上會進行認證的動作,所以請確認填寫無誤。

2-5 最後訊息確認

2-6 訊息確認的同時下方會有E-Mail確認的資訊,此時請到你的E-Mail收件匣中進行確認。

2-7 你會收到一封如下的E-Mail確認信件,請點連結後進行回覆。

2-8 回覆後,確認E-Mail驗證的程序已完成。

2-9 回到剛剛在2-6步驟中,你會看到狀態即會進行改變。

2-10 完成註冊,此時大約仍要等一陣子,新的域名才會進行生效。
2-11 回到Route 53的Dashboard頁面,你即會看到域名的狀態,如下列所示,申請的域名即完成。


3、憑證申請
3-1 開啟ACM(AWS Certificate Manager)畫面,點選 Get started。

3-2 請在下列輸入你要申請的網域名稱,可以輸入多個。

3-3 驗證方式有二種,此步驟,我們選擇Email Validation進行。

3-4 再次確認訊息。

3-5 此時憑證申請的畫面會停在等往網域名稱確認的狀態中。

3-6 此時系統會寄出一封確認信到網域名稱的擁有者信箱中進行確認,格式如下,請點選下方 "Amazon  Certificate Approvals"。


3-7 開啟網頁後,再次進行同意確認。

3-8 確認畫面。

3-9 回到ACM(AWS Certificate Manager),你就會看到憑證完成。

4、ALB(Application Load Balancer)設定
4-1 進入Load Balancers的畫面,選擇建立Application Load Balancer。

4-2 選擇Listeners的Protocol類型與AZ(Availability Zones)區域,由於我的二台主機放在us-east-1c與 us-east-1d,所以我就先選擇這二個區域。

4-3 憑證的部份,我們直接透過ACM(AWS Certificate Manager)進行選擇,系統即會帶出我在步驟3所建立的憑證。

4-4 選擇Security Groups,請記得確認是否有開啟HTTP(80)與HTTPS(443)。

4-5 由於我們希望ALB(Application Load Balancer)支援HTTP與HTTPS,所以這部份選擇HTTP即可。

4-5 ALB的Group主機請將你的主機加入,請記得不是只有勾選,要選擇Add to Registered加入後才算是。

4-6 最後訊息確認

4-7 建立完成後,我們同時透過ALB的DNS進行確認,看是否可以正確的導向二台主機。


5、Custom Domain Name與ALB(Application Load Balancer)的綁定。
5-1 點選網域名稱

5-2 點選Create Record Set

5-3 此時我們將ALB的DNS輸入在下方的區域,然後點選完成。


5-4 最後,我們透過申請的網址名稱與HTTPS的方式進行存取,確認皆可看到連線都正常。


參考連結:
Request a Certificate
https://docs.aws.amazon.com/acm/latest/userguide/gs-acm-request.html
Create an Application Load Balancer
https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-application-load-balancer.html
HTTPS Listeners for Your Application Load Balancer
https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html
Routing Traffic to an ELB Load Balancer
https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-to-elb-load-balancer.html

2018年1月12日 星期五

如何在AWS EC2上以Windows Server 2016建立Microsoft Storage Spaces Direct(S2D)的架構

相信大家對S2D的架構或多或少都知道,其實在Windows 2012 R2的時候就已經有推出支援,但在Windows 2016上又有許多的更新,相關的安裝方式其實在網路上已有許多的參考,所以這篇我要特別整理如何在AWS EC2進行建立,當然安裝上沒有太大的落差,但在一些細部的設定上需要特別的注意,我在此整理出來,也提供給大家參考。

S2D系統架構圖

1、環境準備
AD Server -> Windows 2012 R2
Cluster Node1 -> Windows 2016
Cluster Node2 -> Windows 2016

另外在上述的二個節點上增加各二顆Disk,然後請注意在容量上請選擇相同的大小。

2、環境安裝
2-1 Instance Type選擇
在一開始的的Instance Type的部份,請注意目前測試C5可以進行,因為根據下列的S2D的需求項目一定要符合,要不然在最後建立完Cluster後,當進行Enable-ClusterS2D會出現下列的錯誤訊息,這部份需要再進行注意。


錯誤訊息:
Enable-ClusterS2D:No disks with supported bus types found to be used for S2D.
FullyQualifiedErrorId : HRESULT 0x80070490, Enable-ClusterStorageSpacesDirect

Driver:
Use local-attached SATA, SAS, or NVMe drives.

2-2 Private IP設定

在節點的部份,請特別注意最好設定Private IP在下列的位置上。


3、節點設定與確認
開機登入後,從系統 -> 裝置管理員 -> 確認目前的Disk Drives是否皆為NVMe的類型,如下圖所示。

在建立完成後,請將二個節點分別加入到Cluster中,並確認狀態皆為UP。


4、啟用與設定S2D
4-1 透過Administrator開啟一個PowerShell視窗,並輸入 Enable-ClusterS2D 的功能。

執行完成後,你就可以從 Failover Cluster Manager -> Storage -> Pools中看到已建立一個Cluster Pool。



4-2 透過下列的語法確認目前可能的磁碟。

get-StorageSubSystem Clus* | get-PhysicalDisk

4-3 透過下列的指令進行Volume的建立

New-Volume -StoragePoolFriendlyName S2D* -FriendlyName SQLDataDisk1 -FileSystem CSVFS_NTFS -AllocationUnitSize 65536 -Size 50GB -ProvisioningType Fixed -ResiliencySettingName Mirror

執行過程

4-4 最後建立完成,你就可以到Failover Cluster Manager -> Storage -> Disks的部份看到。



參考連結:
Microsoft SDS 軟體定義儲存技術(2) - S2D 運作架構
https://technet.microsoft.com/zh-tw/mt684933.aspx
Storage Spaces Direct hardware requirements
https://docs.microsoft.com/en-us/windows-server/storage/storage-spaces/storage-spaces-direct-hardware-requirements