AWS CloudFormation - टेम्प्लेट में कस्टम चर


18

क्या CloudFormation टेम्पलेट पैरामीटर से प्राप्त अक्सर उपयोग किए जाने वाले मानों के लिए शॉर्टकट को परिभाषित करने का कोई तरीका है?

उदाहरण के लिए - मुझे एक स्क्रिप्ट मिली है जो ELB नाम के साथ एक मल्टी-AZ प्रोजेक्ट स्टैक बनाती है और ELB के projectपीछे दो उदाहरण project-1और कहा जाता है project-2। मैं केवल ELBHostNameटेम्पलेट को पैरामीटर पास करता हूं और बाद में इसका निर्माण करने के लिए उपयोग करता हूं :

"Fn::Join": [
    ".", [
        { "Fn::Join": [ "", [ { "Ref": "ELBHostName" }, "-1" ] ] },
        { "Ref": "EnvironmentVersioned" },
        { "Ref": "HostedZone" }
    ]
]

यह निर्माण या बहुत समान पूरे टेम्पलेट में कई बार दोहराया जाता है - EC2 होस्ट नाम, रूट 53 रिकॉर्ड आदि बनाने के लिए।

बार-बार यह दोहराने के बजाय कि मैं उस के आउटपुट Fn::Joinको किसी प्रकार के वेरिएबल में असाइन करना चाहूंगा और केवल उसी को संदर्भित कर सकता हूं, जैसे मैं "Ref":बयान कर सकता हूं ।

आदर्श रूप में कुछ इस तरह:

Var::HostNameFull = "Fn::Join": [ ... ]
...
{ "Name": { "Ref": "Var::HostNameFull" } }

या कुछ इसी तरह सरल।

क्या यह अमेज़ॅन क्लाउडफ़ॉर्मेशन के साथ संभव है?


क्या ELBHostName एक ऐसा पैरामीटर है जो आप स्पष्ट रूप से क्लाउडफॉर्म से गुजर रहे हैं? यदि हां, तो रेफ का उपयोग क्यों करें? अपने टेम्प्लेट में वेरिएबल्स को शामिल करने के लिए मूंछों का उपयोग कर सकते हैं और इसे क्लाउडऑफ़ॉर्मेशन से शिपिंग से पहले JSON में बदल सकते हैं। निर्भर करता है कि आप जो प्रोविजनिंग प्रक्रिया कर रहे हैं वह कैसी दिखती है।
कैन्टसन

जवाबों:


5

मैं उसी कार्यक्षमता को देख रहा था। नेस्टेड स्टैक का उपयोग करने के रूप में स्पूनमाइज़र ने सुझाव दिया कि मन में आया, लेकिन फिर मुझे एहसास हुआ कि मुझे वास्तव में जो चाहिए था वह कस्टम फ़ंक्शन था। सौभाग्य से CloudFormation AWS के उपयोग की अनुमति देता है :: CloudFormation :: CustomResource , जो कि थोड़े से काम के साथ, किसी को भी ऐसा करने की अनुमति देता है। यह सिर्फ चर के लिए ओवरकिल की तरह महसूस करता है (कुछ मैं यह तर्क देता हूं कि पहले स्थान पर CloudFormation में होना चाहिए था), लेकिन इसे काम मिल जाता है, और, इसके अलावा, सभी के लचीलेपन के लिए अनुमति देता है (अपना पिकअप / नोड का पिक लें) /जावा)। यह ध्यान दिया जाना चाहिए कि लैम्ब्डा फ़ंक्शंस में पैसे खर्च होते हैं, लेकिन हम यहां पेनीज़ बात कर रहे हैं जब तक कि आप प्रति घंटे कई बार अपना स्टैक नहीं बनाते / हटाते हैं।

पहला कदम इस पृष्ठ पर एक लंबो फ़ंक्शन करना है जो कुछ भी नहीं करता है लेकिन इनपुट मूल्य लेता है और इसे आउटपुट पर कॉपी करता है। हम लैम्बडा फंक्शन को हर तरह के क्रेजी सामान के साथ कर सकते थे, लेकिन एक बार हमारे पास फंक्शन की पहचान होने के बाद, कुछ भी आसान होता है। वैकल्पिक रूप से हम स्टैक में ही लैम्बडा फंक्शन का निर्माण कर सकते थे। चूंकि मैं 1 खाते में कई ढेर लगाता हूं, इसलिए मेरे पास बचे हुए लैम्ब्डा कार्यों और भूमिकाओं का एक पूरा गुच्छा होगा (और सभी ढेरों को बनाने की आवश्यकता है --capabilities=CAPABILITY_IAM, क्योंकि इसमें एक भूमिका भी आवश्यक है।

लैम्ब्डा फंक्शन बनाएं

  • लैम्ब्डा होम पेज पर जाएं , और अपना पसंदीदा क्षेत्र चुनें
  • टेम्पलेट के रूप में "रिक्त फ़ंक्शन" चुनें
  • "अगला" पर क्लिक करें (किसी भी ट्रिगर को कॉन्फ़िगर न करें)
  • भरें:
    • नाम: CloudFormationIdentity
    • विवरण: यह क्या हो जाता है, बादल निर्माण में चर समर्थन देता है
    • रनटाइम: python2.7
    • कोड प्रविष्टि प्रकार: कोड इनलाइन संपादित करें
    • कोड: नीचे देखें
    • हैंडलर: index.handler
    • भूमिका: एक कस्टम भूमिका बनाएँ। इस बिंदु पर एक पॉपअप खुलता है जो आपको एक नई भूमिका बनाने की अनुमति देता है। इस पृष्ठ पर सब कुछ स्वीकार करें और "अनुमति दें" पर क्लिक करें। यह क्लाउडवाच लॉग में पोस्ट करने की अनुमति के साथ एक भूमिका बनाएगा।
    • मेमोरी: 128 (यह न्यूनतम है)
    • टाइमआउट: 3 सेकंड (खूब होना चाहिए)
    • VPC: कोई VPC नहीं

फिर कोड फ़ील्ड में नीचे दिए गए कोड को कॉपी-पेस्ट करें। फ़ंक्शन का शीर्ष cfn-response python मॉड्यूल से कोड है , जो केवल स्वतः स्थापित हो जाता है यदि लैम्ब्डा-फंक्शन CloudFormation के माध्यम से किसी अजीब कारण से बनाया जाता है। handlerसमारोह सुंदर आत्म व्याख्यात्मक है।

from __future__ import print_function
import json

try:
    from urllib2 import HTTPError, build_opener, HTTPHandler, Request
except ImportError:
    from urllib.error import HTTPError
    from urllib.request import build_opener, HTTPHandler, Request


SUCCESS = "SUCCESS"
FAILED = "FAILED"


def send(event, context, response_status, reason=None, response_data=None, physical_resource_id=None):
    response_data = response_data or {}
    response_body = json.dumps(
        {
            'Status': response_status,
            'Reason': reason or "See the details in CloudWatch Log Stream: " + context.log_stream_name,
            'PhysicalResourceId': physical_resource_id or context.log_stream_name,
            'StackId': event['StackId'],
            'RequestId': event['RequestId'],
            'LogicalResourceId': event['LogicalResourceId'],
            'Data': response_data
        }
    )
    if event["ResponseURL"] == "http://pre-signed-S3-url-for-response":
        print("Would send back the following values to Cloud Formation:")
        print(response_data)
        return

    opener = build_opener(HTTPHandler)
    request = Request(event['ResponseURL'], data=response_body)
    request.add_header('Content-Type', '')
    request.add_header('Content-Length', len(response_body))
    request.get_method = lambda: 'PUT'
    try:
        response = opener.open(request)
        print("Status code: {}".format(response.getcode()))
        print("Status message: {}".format(response.msg))
        return True
    except HTTPError as exc:
        print("Failed executing HTTP request: {}".format(exc.code))
        return False

def handler(event, context):
    responseData = event['ResourceProperties']
    send(event, context, SUCCESS, None, responseData, "CustomResourcePhysicalID")
  • अगला पर क्लिक करें"
  • "क्रिएट फंक्शन" पर क्लिक करें

अब आप "टेस्ट" बटन का चयन करके लंबो फ़ंक्शन का परीक्षण कर सकते हैं, और नमूना टेम्पलेट के रूप में "क्लाउडफ़ॉर्मेशन क्रिएट रिक्वेस्ट" का चयन कर सकते हैं। आपको अपने लॉग में देखना चाहिए कि चर उसे खिलाया जाता है, वापस कर दिया जाता है।

अपने CloudFormation टेम्पलेट में चर का उपयोग करें

अब जब हमारे पास यह लंबा फ़ंक्शन है, तो हम इसे क्लाउडफ़ॉर्मेशन टेम्प्लेट में उपयोग कर सकते हैं। सबसे पहले लैम्ब्डा फंक्शन अर्न पर ध्यान दें ( लैम्ब्डा होम पेज पर जाएं , बस बनाए गए फंक्शन पर क्लिक करें, अर्न को टॉप राईट में होना चाहिए, कुछ ऐसा arn:aws:lambda:region:12345:function:CloudFormationIdentity)।

अब संसाधन अनुभाग में अपने टेम्पलेट में, अपने चर निर्दिष्ट करें जैसे:

Identity:
  Type: "Custom::Variable"
  Properties:
    ServiceToken: "arn:aws:lambda:region:12345:function:CloudFormationIdentity"
    Arn: "arn:aws:lambda:region:12345:function:CloudFormationIdentity"

ClientBucketVar:
  Type: "Custom::Variable"
  Properties:
    ServiceToken: !GetAtt [Identity, Arn]
    Name: !Join ["-", [my-client-bucket, !Ref ClientName]]
    Arn: !Join [":", [arn, aws, s3, "", "", !Join ["-", [my-client-bucket, !Ref ClientName]]]]

ClientBackupBucketVar:
  Type: "Custom::Variable"
  Properties:
    ServiceToken: !GetAtt [Identity, Arn]
    Name: !Join ["-", [my-client-bucket, !Ref ClientName, backup]]
    Arn: !Join [":", [arn, aws, s3, "", "", !Join ["-", [my-client-bucket, !Ref ClientName, backup]]]]

पहले मैं एक Identityचर निर्दिष्ट करता हूं जिसमें लैम्बडा फ़ंक्शन के लिए अर्न होता है। इसे एक चर में यहाँ लाना, इसका मतलब है कि मुझे केवल एक बार इसे निर्दिष्ट करना होगा। मैं अपने सभी प्रकार के चर बनाता हूं Custom::Variable। CloudFormation आपको Custom::कस्टम संसाधनों के साथ शुरू होने वाले किसी भी प्रकार के नाम का उपयोग करने की अनुमति देता है ।

ध्यान दें कि Identityचर में लैम्बडा फ़ंक्शन के लिए दो बार अर्न होता है। एक बार उपयोग करने के लिए लंबो फ़ंक्शन को निर्दिष्ट करने के लिए। चर के मान के रूप में दूसरी बार।

अब जब मेरे पास Identityचर है, तो मैं नए चर का उपयोग करके परिभाषित कर सकता ServiceToken: !GetAtt [Identity, Arn]हूं (मुझे लगता है कि JSON कोड कुछ ऐसा होना चाहिए "ServiceToken": {"Fn::GetAtt": ["Identity", "Arn"]})। मैं 2 नए चर बनाता हूं, जिनमें से प्रत्येक में 2 क्षेत्र हैं: नाम और अर्न। अपने टेम्पलेट के बाकी हिस्सों में मैं उपयोग कर सकता हूं !GetAtt [ClientBucketVar, Name]या !GetAtt [ClientBucketVar, Arn]जब भी मुझे इसकी आवश्यकता होगी।

सावधानी का शब्द

कस्टम संसाधनों के साथ काम करते समय, यदि लैम्ब्डा फ़ंक्शन क्रैश हो जाता है, तो आप 1 और 2 घंटे के बीच फंस जाते हैं, क्योंकि CloudFormation देने से पहले एक घंटे के लिए (क्रैश) फ़ंक्शन के उत्तर की प्रतीक्षा करता है। इसलिए आपके लंबो फ़ंक्शन को विकसित करते समय स्टैक के लिए थोड़े समय के लिए निर्दिष्ट करना अच्छा हो सकता है।


बहुत बढ़िया जवाब! मैंने इसे पढ़ा और इसे अपने ढेर में चला दिया, हालांकि मेरे लिए, मैं अपने खाते में लंबो कार्यों के प्रसार के बारे में चिंता नहीं करता हूं और मुझे ऐसे टेम्पलेट पसंद हैं जो स्टैंडअलोन हैं (मैं cloudformation-toolरत्न का उपयोग करके संशोधित करता हूं ), इसलिए मैं लंबोदर के निर्माण को पैक करता हूं। टेम्पलेट और फिर Identityकस्टम संसाधन बनाने के बजाय सीधे इसका उपयोग कर सकते हैं । मेरे कोड के लिए यहाँ देखें: gist.github.com/guss77/2471e8789a644cac96992c4102936fb3
Guss

जब आप "... आप 1 और 2 घंटे के बीच फंस गए हैं ..." क्योंकि एक लंबोदा दुर्घटनाग्रस्त हो गया और वापस cfn-प्रतिक्रिया के साथ जवाब नहीं दिया, तो आप कर्ल / विग का उपयोग करके मैन्युअल रूप से टेम्पलेट को फिर से प्राप्त कर सकते हैं हस्ताक्षरित URL। लैम्ब्डा की शुरुआत में हमेशा ईवेंट / URL को प्रिंट करना सुनिश्चित करें ताकि आप क्लाउडवॉच पर जा सकें और URL हैंग कर सकें।
टेलर

12

मेरे पास कोई उत्तर नहीं है, लेकिन मैं यह बताना चाहता हूं कि आप इसके Fn::Subस्थान पर उपयोग करके खुद को बहुत दर्द से बचा सकते हैंFn::Join

{ "Fn::Sub": "${ELBHostName"}-1.${EnvironmentVersioned}.${HostedZone}"}

के स्थान पर

"Fn::Join": [
    ".", [
        { "Fn::Join": [ "", [ { "Ref": "ELBHostName" }, "-1" ] ] },
        { "Ref": "EnvironmentVersioned" },
        { "Ref": "HostedZone" }
    ]
]

3

नहीं, मैंने कोशिश की, लेकिन खाली आया। जिस तरह से मेरे लिए समझ में आया वह था "कस्टमवेरीएबल्स" नामक एक मैपिंग एंट्री बनाना और उस घर को मेरे सभी वेरिएबल्स में रखना। यह साधारण स्ट्रिंग्स के लिए काम करता है, लेकिन आप मैपिंग के अंदर आंतरिक (Refs, Fn :: Joins, आदि) का उपयोग नहीं कर सकते

काम करता है:

"Mappings" : {
  "CustomVariables" : {
    "Variable1" : { "Value" : "foo" },
    "Variable2" : { "Value" : "bar" }
  }
}

काम नहीं करेगा:

  "Variable3" : { "Value" : { "Ref" : "AWS::Region" } }

वह सिर्फ एक उदाहरण है। आप एक परिवर्तनीय में एक स्टैंडअलोन रेफरी नहीं डालेंगे।


1
दस्तावेज़ीकरण कहता है कि मानचित्रण मूल्यों को शाब्दिक तार होना चाहिए।
इवान अनिशचुक

3

आप एक नेस्टेड स्टैक का उपयोग कर सकते हैं जो आपके सभी चर को आउटपुट में हल करता है, और फिर Fn::GetAttउस स्टैक से आउटपुट को पढ़ने के लिए उपयोग करें


2

आप नेस्टेड टेम्प्लेट का उपयोग कर सकते हैं जिसमें आप अपने सभी वैरिएबल को बाहरी टेम्प्लेट में "हल" करते हैं और उन्हें दूसरे टेम्प्लेट में पास करते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.